本質(zhì)上,python中所有的屬性和方法都是公開的满哪,在類的外部可以使用和繼承
1.私有化
讓屬性和方法只能在類的內(nèi)部使用,不能在類的外部使用
1.1.語法:
聲明屬性或者方法的時候蛮原,在屬性名或者方法名前加'__'
1.2.python私有化的原理
python并不能想java一樣從訪問權(quán)限上去限制屬性和方法贸铜,沒有真正的私有屬性和方法秽五。
私有化只是在兩個下劃線開頭的名字前加前綴'_類名'孽查,導(dǎo)致不能直接通過原名進行訪問
2.對象屬性的保護:
不要直接訪問或者修改對象屬性的值,而是通過屬性訪問器(getter)和修改器(setter)去操作對象屬性
需要添加getter或者setter的對象屬性坦喘,屬性命名的時候需要在最前面加'_'盲再。
(添加'_'的目的是為了告訴使用者西设,這個屬性添加了getter或者setter)
2.1.getter - 獲取屬性(間接)
2.1.1.語法:
@property
def 函數(shù)名(self):
其他語句
return 屬性名
2.2.2.說明:
函數(shù)名 - 對應(yīng)的屬性名去掉下劃線
屬性值 - 和對應(yīng)的有下劃線的屬性值有關(guān)聯(lián)
2.2.3.什么時候用:
如果希望在獲取某個屬性的值之前干點別的事情,就給這個屬性添加getter
class Student:
def __init__(self, name):
self._name = name
self._week = 1
@property
def name(self):
return self._name
@property
def week(self):
if 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 '星期六'
elif self._week == 7:
return '星期日'
def hello(self):
print(self.week)
stu1 = Student('leihaoya')
print(stu1._name)
print(stu1.name) # 通過不帶下劃線去獲取屬性的值的時候答朋,本質(zhì)是在調(diào)用屬性對應(yīng)的getter方法贷揽,結(jié)果是getter的返回值
print(stu1.week)
stu1.hello()
2.2.setter - 給屬性賦值(間接)
想要添加setter必須先添加getter
2.2.1.語法:
@getter名.setter
def 函數(shù)名(self, 參數(shù))
其他語句
self.屬性 = 參數(shù)
2.2.2.什么時候用
如果在給屬性賦值前有要求,就可以使用setter
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if isinstance(value, int):
if 0 <= value <= 200:
self._age = value
else:
print('年齡必須為0~200歲之間梦碗!')
else:
print('年齡必須為正整數(shù)禽绪!')
stu1.age = 100
print(stu1.age)
stu1.age = 'abc'
stu1.age = 300
練習(xí):聲明矩形類,有屬性:長洪规、寬印屁、周長、面積斩例。要求修改長和寬的值的時候雄人,周長和面積自動變化。
并且不能修改周長和面積的值(如果主動給周長和面積賦值,程序直接報錯)
class WriteError(Exception):
def __str__(self):
return '嘗試修改一個只讀的屬性'
class Rectangle:
def __init__(self):
self._length = 0
self._width = 0
self._perimeter = 0
self._area = 0
@property
def length(self):
return self._length
@property
def width(self):
return self._width
@length.setter
def length(self, value):
self._length = value
self._perimeter = 2 * (self._length + self._width)
self._area = self._length * self._width
@width.setter
def width(self, value):
self._width = value
self._perimeter = 2 * (self._length + self._width)
self._area = self._length * self._width
@property
def perimeter(self):
return self._perimeter
@perimeter.setter
def perimeter(self, value):
raise WriteError
@property
def area(self):
return self._area
@area.setter
def area(self, value):
raise WriteError
r1 = Rectangle()
r1.length = 5
r1.width = 4
print(r1.perimeter, r1.area)
r1.area = 21
method(方法)
1.類中的方法:對象方法、類方法毙替、靜態(tài)方法
1.1.對象方法
1.1.1.怎么聲明:
直接聲明在類中
1.1.2.特點:
有默認(rèn)參數(shù)self;調(diào)用的時候不用傳參旗吁,指向當(dāng)前對象
1.1.3.怎么調(diào)用:
通過對象來調(diào)用(對象.對象方法())
1.1.4.什么時候用:
如果實現(xiàn)函數(shù)的功能,需要使用對象屬性停局,就用對象方法
1.2.類方法
1.2.1.怎么聲明:
聲明函數(shù)前添加@classmethod裝飾器
1.2.2.特點:
有默認(rèn)參數(shù)cls很钓;調(diào)用的時候不用傳參,系統(tǒng)將調(diào)用這個方法的類傳給它翻具,指向當(dāng)前類
1.2.3.怎么調(diào)用:
通過類來調(diào)用
1.2.4.什么時候用:
在不需要對象屬性的前提下履怯,需要類的字段,就使用類方法
1.3.靜態(tài)方法
1.3.1.怎么聲明:
聲明前添加@staticmethod裝飾器
1.3.2.特點:
沒有默認(rèn)參數(shù)
1.3.3.怎么調(diào)用:
通過類來調(diào)用
1.3.4.什么時候用:
既不需要對象屬性裆泳,也不需要類的字段,就使用靜態(tài)方法
inherit
1.繼承
繼承者 - 子類
被繼承者 - 父類
繼承 - 讓子類直接擁有父類的屬性和方法
1.1.語法:
class 類名(父類):
類的內(nèi)容
2.在子類中添加內(nèi)容
2.1.在子類中添加字段和方法
直接在子類中聲明新的字段和方法
2.2.添加對象屬性
在子類中實現(xiàn)__init__方法柠硕,并且添加新屬性工禾。同時需要通過super().__init__()去調(diào)用父類的__init__方法
補充:類中的函數(shù)的調(diào)用過程
先看當(dāng)前類中是否有這個方法,如果有直接調(diào)用自己的方法蝗柔;沒有就去看父類有沒有這個方法闻葵,如果有就調(diào)用父類的方法;如果父類也沒有就繼續(xù)找父類的父類癣丧,以此類推槽畔,直到找到object都沒有找到這個方法,才報錯胁编!
python中所有的類默認(rèn)都是繼承object厢钧,object是python中所有類的基類
2.3.重新方法
在子類中重新實現(xiàn)父類的函數(shù)鳞尔;可以通過super()去調(diào)用父類中的方法。
注意:super()不能在靜態(tài)方法中使用早直,只能在對象方法和類方法中使用