进阶面向对象——类的成员
類的成員可以分為三大類:字段、方法、屬性。
? ??
@:所有成員中,只有普通字段的內(nèi)容保存在對(duì)象中,即:根據(jù)此類創(chuàng)建了多少對(duì)象,在內(nèi)存中就有多少普通字段。而其他的成員都是保存在類中的,即:無論對(duì)象的多少,在內(nèi)存中只創(chuàng)建一份。
?
一、字段:(普通字段和靜態(tài)字段)
1、普通字段:屬于對(duì)象
2、靜態(tài)字段:屬于類
class Yitian:#靜態(tài)字段user = "張無忌"def __init__(self,name):#普通字段self.name = name#直接訪問普通字段 obj = Yitian("明教") print(obj.name)#直接訪問靜態(tài)字段 print(Yitian.user)@普通字段需要通過對(duì)象來訪問,靜態(tài)方法通過類訪問。(兩者的歸屬不同)
由圖可知:
靜態(tài)字段在內(nèi)存中只保存一份
普通字段在每個(gè)對(duì)象中都要保存一份
class Yitian:#靜態(tài)字段user = "張無忌"def __init__(self,name):#普通字段self.name = name#直接訪問普通字段 obj1 = Yitian("明教") obj2 = Yitian("峨眉") print(obj1.name) print(obj2.name) #增加了一個(gè)對(duì)象”峨眉“#直接訪問靜態(tài)字段 Yitian.user = "周芷若" #改變了靜態(tài)字段 結(jié)果:周芷若 print(Yitian.user) #最終結(jié)果:周芷若?
應(yīng)用的場景:通過類創(chuàng)建對(duì)象時(shí),如果每個(gè)對(duì)象都具有相同字段,那么就用靜態(tài)字段。
?
二、方法:(普通方法、靜態(tài)方法、類方法-->在內(nèi)存中都?xì)w屬于類,調(diào)用方式不同)
1、普通方法:
由對(duì)象調(diào)用,至少一個(gè)self參數(shù),執(zhí)行普通方法時(shí),自動(dòng)將調(diào)用該方法的對(duì)象賦值給self。
2、類方法:
由類方法調(diào)用,至少一個(gè)cls參數(shù),執(zhí)行方法時(shí),自動(dòng)將調(diào)用該方法的類復(fù)制給cls.
3、靜態(tài)方法:?
? 由類調(diào)用,無默認(rèn)值參數(shù)。
class Foo:def __init__(self,name):self.naem = namedef ord_func(self):'''定義一個(gè)普通方法,至少有一個(gè)self參數(shù)'''print(self.naem)print("普通方法")@classmethoddef class_func(cls):'''定義一個(gè)類方法,至少一個(gè)cls參數(shù)'''print("類方法")@staticmethoddef static_func():'''定義一個(gè)靜態(tài)方法,無默認(rèn)值參數(shù)'''print("靜態(tài)方法") #調(diào)用普通方法 f = Foo() f.ord_func()#調(diào)用類方法 Foo.class_func()#調(diào)用靜態(tài)方法 Foo.static_func()@區(qū)別:
相同點(diǎn):對(duì)于所有的方法而言,均屬于類(非對(duì)象)中,所以在內(nèi)存中也只保存一份。
不同點(diǎn):方法調(diào)用者不同、調(diào)用方法時(shí)自動(dòng)傳入的參數(shù)不同。
?
三、屬性:
1、屬性的基本使用:
#==========定義================= class Doo:def func(self):pass#定義屬性@propertydef prop(self):pass #=========調(diào)用=============== doo_obj = Doo() doo_obj.func() doo_obj.prop #調(diào)用屬性@定義屬性的注意事項(xiàng):
定義時(shí),在普通方法的基礎(chǔ)上添加@property裝飾器
定義時(shí),屬性僅有一個(gè)self參數(shù)
調(diào)用時(shí),無需括號(hào)
方法:obj.func()
屬性:obj.prop ? #沒有括號(hào)
屬性存在的意義是:訪問屬性時(shí)可以制造出和訪問字段完全相同的假象
屬性由方法變種而來,如果python中沒有屬性,方法完全可以代替其功能。
#例: 分頁顯示請(qǐng)求的頁面的數(shù)據(jù) class Pager:def __init__(self,current_page):#用戶當(dāng)前請(qǐng)求的頁碼self.current_page = current_page#每頁默認(rèn)顯示10條數(shù)據(jù)self.per_intems = 10@propertydef start(self):val = (self.current_page - 1) * self.per_intemsreturn val@propertydef end(self):val = self.current_page * self.per_intemsreturn val #調(diào)用 p = Pager(10) print(p.start) print(p.end)@python屬性的功能是:屬性內(nèi)部進(jìn)行一系列的邏輯計(jì)算,最終將計(jì)算結(jié)果返回
?
2、屬性的兩種定義方式
? (1)、裝飾器:在方法上應(yīng)用裝飾器
裝飾器方式:在類的普通方法上應(yīng)用@property裝飾器
經(jīng)典類:具有一種@property裝飾器
#==========定義========= class Goods:@propertydef price(self):return "張無忌" # ======調(diào)用========== obj = Goods() result = obj.price #自動(dòng)執(zhí)行@property修飾方法,并獲取方法的返回值。 print(result)新式類:具有三種@property裝飾器
#======定義======= class Goods:@propertydef price(self):print("張無忌")@price.setterdef price(self,value):print("周芷若")# print(value) @price.deleterdef price(self):print("趙敏") # =====調(diào)用============ obj = Goods() obj.price #自動(dòng)執(zhí)行@property修飾的price方法,并獲取方法的返回值 obj.price = 123 #自動(dòng)執(zhí)行@property.setter修飾的price方式,并將123賦值給方法的參數(shù) del obj.price #自動(dòng)執(zhí)行@price.deleter修飾的price方法@? 經(jīng)典類中的屬性只有一種訪問方式,其對(duì)應(yīng)被@property修飾的方法
? 新式類中的屬性有三種訪問方式,并分別對(duì)應(yīng)了三個(gè)被@property、@方法名.setter、@方法名.deleter修飾的方法。(由于新式類中具有三種訪問方式,根據(jù)他們幾個(gè)屬性訪問特點(diǎn),分別將三個(gè)方法定義為對(duì)同一個(gè)屬性:獲取、修改、刪除)
class Goods:def __init__(self):#原價(jià)self.original_price = 10#折扣self.discount = 0.8@propertydef price(self):#實(shí)際價(jià)格 = 原價(jià) * 折扣new_price = self.original_price * self.discountreturn new_price@price.setterdef price(self,value):self.original_price = value@price.deleterdef price(self):del self.original_priceobj = Goods() print(obj.price) #獲取商品價(jià)格 update = obj.price = 200 #修改商品原價(jià) print(update) del obj.price #刪除商品原價(jià)?
(2)、靜態(tài)字段:在類中定義值為property對(duì)象的靜態(tài)字段
? 當(dāng)使用靜態(tài)字段的方式創(chuàng)建屬性時(shí),經(jīng)典類和新式類無區(qū)別
class Foo:def get_bar(self):return "張無忌"BAR = property(get_bar)obj = Foo() reuslt = obj.BAR #自動(dòng)調(diào)用get_bar方法,并獲取方法的返回值 print(reuslt)# 結(jié)果:張無忌property的構(gòu)造方法中有四個(gè)參數(shù)
第一個(gè)參數(shù)是方法名,調(diào)用對(duì)象.屬性 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
? 第二個(gè)參數(shù)是方法名,調(diào)用對(duì)象.屬性 =xxx 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
第三個(gè)參數(shù)是方法名,調(diào)用del 對(duì)象.屬性 時(shí)自動(dòng)觸發(fā)執(zhí)行方法
第四個(gè)參數(shù)是字符串,調(diào)用對(duì)象.屬性.__doc__,此參數(shù)是該屬性的描述信息
class Foo:def get_bar(self):return "張無忌"#必須兩個(gè)參數(shù)def set_bar(self,value):return "set value" + valuedef del_bar(self):return "周芷若"BAR = property(get_bar,set_bar,del_bar,"description...")obj = Foo() obj.BAR #自動(dòng)調(diào)用第一個(gè)參數(shù)中定義的方法:get_bar obj.BAR = "趙敏" #自動(dòng)調(diào)用第二個(gè)參數(shù)中定義的方法:set_bar,并將“趙敏”當(dāng)作參數(shù)傳入 del Foo.BAR #自動(dòng)調(diào)用第三個(gè)參數(shù)中定義的方法:del_bar方法 obj.BAR.__doc__ #自動(dòng)獲取第四個(gè)參數(shù)中設(shè)置的值description...由于靜態(tài)字段方式創(chuàng)建屬性具有三種訪問方式,我們可以根據(jù)他們幾個(gè)屬性的訪問特點(diǎn)分別將三個(gè)方法定義位獲取、修改、刪除
class Googs(object):def __init__(self):self.original_price = 100 #原價(jià)self.discount = 0.8 #折扣self.WW = 22def get_price(self):#實(shí)際價(jià)格 = 原價(jià) * 折扣new_price = self.original_price * self.discountreturn new_pricedef set_price(self,value):self.original_price = valuedef del_price(self):del self.WWPRICE = property(get_price, set_price, del_price, "價(jià)格屬性描述。。。") obj = Googs() print(obj.PRICE) #獲取商品價(jià)格 obj.PRICE = 200 #修改商品原價(jià) del obj.PRICE #刪除商品原價(jià)所以在定義屬性共有兩種方式,分別是【裝飾器】和【靜態(tài)字段】,而【裝飾器】方式針對(duì)經(jīng)典類和新式類又有所不同。
?
四、類成員修飾符
對(duì)于每一個(gè)類的成員而言都有兩種形式:
共有成員,在任何地方都能訪問
私有成員,只有在類的內(nèi)部才能訪問
1、私有成員的和共有成員的定義不同
私有成員命名時(shí),前兩個(gè)字符時(shí)下劃線。(特殊成員除外,例如:__init__、__call__、__dict__等)
class Foo:def __init__(self):self.name = "張無忌" #公有字段self.__age = 20 #私有字段2、私有成員和共有成員的訪問限制不同:
(1)、靜態(tài)字段
公有靜態(tài)字段:類可以訪問;類內(nèi)部可以訪問,派生類中可以訪問
class Foo:name = "張無忌" #公有靜態(tài)字段def func(self): print(Foo.name) class Doo(Foo):def show(self):print(Foo.name)Foo.name #類訪問 obj = Doo() obj.func() #內(nèi)部類可以訪問 obj_son = Doo() obj_son.show() #派生類中可以訪問私有靜態(tài)字段:僅類內(nèi)部可以訪問
class Foo:__name = "張無忌" #私有靜態(tài)字段def func(self):print(Foo.__name) class Doo(Foo):def show(self):print(Foo.__name)Foo.name #類訪問 ---錯(cuò)誤 obj = Doo() obj.func() #內(nèi)部類可以訪問 ---正確 obj_son = Doo() obj_son.show() #派生類中可以訪問 ---錯(cuò)誤? (2)、普通字段
共有普通字段:對(duì)象可以訪問,內(nèi)部類可以訪問、派生類可以訪問
class Foo:def __init__(self):self.foo = "周芷若" #公有字段def func(self):print(self.foo) #類內(nèi)部訪問class Doo(Foo):def show(self):print(self.foo) #派生類中訪問 obj = Foo()obj.foo #通過對(duì)象訪問 obj.func() #類內(nèi)部訪問 obj_son = Doo() obj_son.show() #派生類中訪問私有普通字段:僅類內(nèi)部可以訪問
@如果想要強(qiáng)制訪問私有字段,可以通過[對(duì)象._類名__私有字段名]訪問,(例如:obj._Foo__foo),不建議強(qiáng)制訪問私有成員。
class Foo:def __init__(self):self.__foo = "周芷若" #私有字段def func(self):print(self.__foo) #類內(nèi)部訪問class Doo(Foo):def show(self):print(self.__foo) #派生類中訪問 ---錯(cuò)誤 obj = Foo()obj.foo #通過對(duì)象訪問 ---錯(cuò)誤 obj.func() #類內(nèi)部訪問 ---正確 obj_son = Doo() obj_son.show() #派生類中訪問 ---錯(cuò)誤@方法、屬性的訪問于上述方式相似,即:私有成員只能子啊類內(nèi)部是用
@非要訪問私有屬性的話,可以通過 對(duì)象._類__屬性名
?
五、類的特殊成員
1、__doc__
2、__module__和__class__
3、__init__
4、__del__
5、__call__
6、__dict__
7、__str__
8、__getitem__、__setitem__、__delitem__
9、__getslice__、__setslice__、__delslice__
10、__iter__
11、__new__和__metaclass__
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/LW-5208/articles/9545961.html
總結(jié)
以上是生活随笔為你收集整理的进阶面向对象——类的成员的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux监控命令之==top
- 下一篇: 查询数据库游标使用情况以及sql