一、昨日內容復習
1.類:擁有相同屬性和相同功能的對象的集合(抽象)
屬性 -> 存儲數據(對象屬性,類的字段)
功能 -> 方法(對象方法,類方法和靜態方法)
class 類名(父類):
類的內容
2.對象: 類的實例(具體)
對象 = 類名()
3.構造方法和init方法
構造方法: 聲明類的時候,系統會自動創建一個函數,這個函數的函數名和類名一樣。這個方法就是構造方法。
構造的作用就是創建對象,并且自動的去調用init方法
init方法:a.系統在創建對象的時候自動調用。
b.可以有除了self以外的其他參數,如果要給這些參數傳參,需要使用構造方法來傳
c.需要給類添加對象屬性
- 構造方法給init方法傳參的原理:
# 偽代碼
# def Person():
# obj = malloc(4)
# obj.__init__()
# return obj
# 構造方法給init方法傳參的原理
# def dog_init(name, age, sex):
# print(name, age, sex)
#
# def Dog(*args, **kwargs):
# dog_init(*args, **kwargs)
#
# Dog('abc', 23, sex='男')
4.對象方法: 直接聲明在類中的函數就是對象方法,有默認參數self,并且要通過對象,調用的時候不用給self傳參
對象.對象方法,系統會將前面的對象傳遞給對象方法中的self
5.對象的屬性
a.聲明在init方法中
b.self.屬性 = 值
要通過對象去使用(增刪改查)
6.類的字段(類的屬性)
聲明在類中,函數的外面的變量;通過類來使用(不管在哪兒用)
7.對象.__dict__
二、類方法和靜態方法
類中方法:對象方法、類方法和靜態方法
1.對象方法:
a.直接聲明在類中
b.自帶參數self
c.通過對象來調用
2.類方法:
a.將函數聲明在@classmethod后面的函數就是類方法
b.自帶參數cls(cls在函數調用的時候不用傳參,系統會自動將調用這個方法的類賦給它)
c.通過類來調用
3.靜態方法:
a.聲明在@staticmethod后面的函數就是靜態方法
b.沒有自帶參數
c.通過類來調用
4.怎么選擇使用哪種方法(重點!!!):
對象方法:如果實現函數的功能需要用到對象的屬性,那么就把這個函數聲明成對象方法
靜態方法和類方法:實現函數的功能不需要用到對象的屬性,就可以使用靜態方法或者類方法
類方法:在不使用對象屬性的前提下,需要使用類
靜態方法:既不需要對象的屬性,也不需要類
class Person:
num = 61
# 聲明一個類方法
@classmethod
def destory(cls):
# cls指向的是當前類,調用這個方法的類可以做的事情,cls都能做
print('cls:', cls, cls.num)
p2 = cls()
print('人類破壞環境')
# 聲明一個靜態方法
@staticmethod
def func1():
print(Person.num)
p3 = Person()
print(p3)
print('人類的靜態方法')
Person.destory()
print(Person)
print(Person.num)
p1 = Person()
class Student(Person):
pass
Student.func1()
Student.destory()
Person.func1()
Person.destory()
# cls: <class '__main__.Person'> 61
# 人類破壞環境
# <class '__main__.Person'>
# 61
# 61
# <__main__.Person object at 0x00000000024D6588>
# 人類的靜態方法
# cls: <class '__main__.Student'> 61
# 人類破壞環境
# 61
# <__main__.Person object at 0x00000000024D6630>
# 人類的靜態方法
# cls: <class '__main__.Person'> 61
# 人類破壞環境
class Math:
pi = 3.1415926
@classmethod
def circle_area(cls, radius):
return cls.pi * radius ** 2
@staticmethod
def sum(num1, num2):
return num1 + num2
class Number:
def __init__(self):
self.value = 0
self.type = int
self.id = None
@staticmethod
def max():
return 100
@staticmethod
def min():
return -100
num = Number()
num.value = 1000
print(Number.max()) # 100
三、私有化
類中的內容默認都是公開的(在類的外面可以使用)
1.私有化
將類的內容在類的外面隱藏
在類中的方法名或者屬性名前加兩個下劃線
私有的方法和屬性,只能在類的內部使用,不能在類的外部使用
2.私有的原理
python中沒有真正的私有化(沒有從訪問權限上去限制內容的訪問)
私有的原理就是在私有的屬性名或者方法名前加前綴'_類名',來阻止外部直接通過帶兩個下劃線的名字去使用私有屬性和方法
class Person:
# 私有字段
__num = 61
def __init__(self, name, age):
self.name = name
# 私有的對象屬性
self.__age = age
def show_age(self):
print(self.__age)
self.__func1()
# 私有的對象方法
def __func1(self):
print('私有對象方法')
p1 = Person('小明', 23)
print(p1.name)
# print(p1.age) # AttributeError: 'Person' object has no attribute 'age'
# print(p1.__age) # AttributeError: 'Person' object has no attribute 'age'
p1.show_age()
# 23
# 私有對象方法
# p1.__func1() # AttributeError: 'Person' object has no attribute 'age'
print(p1.__dict__) # {'name': '小明', '_Person__age': 23}
print(p1._Person__age) # 23
四、getter和setter
1.什么時候需要添加對象屬性的getter和setter
如果希望在通過對象.屬性獲取屬性的值之前,再干點兒別的事情,就可以給這個屬性添加getter
如果希望在通過對象.屬性給屬性賦值之前,再干點兒別的事情,就可以給這個屬性添加setter
2.怎么添加setter和getter
getter:
a.在屬性名前加_
b.添加屬性對應的getter
@property
def 屬性名去掉_(self):
函數體 --> 會對屬性的值進行處理后返回相應的結果(必須要有返回值)
c.使用屬性的值的時候,不通過帶下劃線的屬性名去使用,而是通過沒有下劃線的屬性去使用
注意:對象.不帶下劃線的屬性 --> 調用getter對應的函數
自己備注的:(property是去掉調用函數時的括號,并且將函數返回值作為函數名的值)
setter:
如果要添加setter,必須要先添加getter
a.添加setter
@getter名.setter
def 屬性名去掉_(self,參數):
做別的事情
self.屬性名 = 處理后的值
class Number:
def __init__(self):
self._value = 0
# 通過0-6保存星期幾
self._week = 0
self.type = int
self.id = None
@property
def value(self):
return self._value
@value.setter
def value(self, x):
if not -100<=x<=100:
raise ValueError
self._value = x
# _week的getter
@property
def week(self):
if self._week == 0:
return '星期天'
elif self._week == 1:
return '星期一'
elif self._week == 2:
return '星期二'
elif self._week == 3:
return '星期三'
elif self._week == 4:
return '星期四'
elif self._week == 5:
return '星期五'
elif self._week == 6:
return '星期六'
"""
isinstance(值, 類) --> 判斷指定的值是否是指定類型(返回值是bool)
"""
@week.setter
def week(self, value):
if not isinstance(value, int):
raise ValueError
if not 0<=value<=6:
raise ValueError
self._week = value
@staticmethod
def max():
return 100
@staticmethod
def min():
return -100
num = Number()
print(num.week) # 星期天 # num.week實質是在通過num對象調用getter對應的對象方法week
print(num._week) # 0
# num.week = '1' # ValueError
num.week = 1 # num.week = 值 實質是通過num對象去調用setter對應的week方法
# num.week = 10 # ValueError
# num.value = 1000 # ValueError
練習:
class Person:
def __init__(self):
self.name
self.age
賦值時要求age的值只能在0-150之間,超過范圍報錯;獲取age的值的時候,返回年齡值,并且返回這個年齡對應的階段和值
class Person:
def __init__(self):
self.name = ''
self._age = 18
@property
def age(self):
if 0<=self._age<=3:
return '年齡:' + str(self._age) + ', 階段:嬰兒'
elif 4<=self._age<=12:
return '年齡:' + str(self._age) + ', 階段:兒童'
elif 13<=self._age<=17:
return '年齡:' + str(self._age) + ', 階段:少年'
elif 18<=self._age<=29:
return '年齡:' + str(self._age) + ', 階段:青年'
elif 30<=self._age<=59:
return '年齡:' + str(self._age) + ', 階段:中年'
elif 60<=self._age<=150:
return '年齡:' + str(self._age) + ', 階段:老年'
@age.setter
def age(self, value):
if not 0<=value<=150:
raise ValueError
self._age = value
age1 = random.randint(0,150)
p1 = Person()
p1.age = age1
print(p1.age)
# p2 = Person()
# p2.age = 151 # ValueError