(點選上方公衆号,可快速關注一起學Python)
作者:浪子燕青 連結:
http://www.langzi.fun/深入類與對象-中.html
類屬性和執行個體屬性查找順序
屬性:在内部定義的方法或者變量
使用代碼:
class magic:
a = 'langzi'
def __init__(self,x):
self.x = x
# 這裡傳入的x已經屬于這個對象
def run(self):
return self.x
m = magic('xx')
m.a = 'LANGZILANGZI'
print(m.a)
# 查找執行個體的屬性
print(magic.a)
# 查找類的屬性
print(m.x)
# 查找執行個體的屬性
傳回結果:
'LANGZILANGZI'
'langzi'
'xx'
查找順序是由下而上的查找順序,init是初始化執行個體的屬性,要記住這裡使用magic.x是會報錯的,因為init是初始化執行個體,這個執行個體成為m,并不在屬于magic。
可能這樣舉例子不清晰,重新再看看代碼
class magic:
name = '浪子'
def __init__(self,name):
self.name = name
m = magic('langzi')
print(m.name)
print(magic.name)
傳回結果:
langzi
浪子
這樣是不是就比較清晰了,類中的name=’浪子’是屬于magic類當中的,執行個體m.name是屬于執行個體m當中的,是在類中init初始化的屬性。
他們的查找順序是這樣:
- 找m.name的時候,由下而上,會先找到m。
- 找到m的初始話對象,從init開始查找,就會找到初始化傳入的name
- 如果init中沒有name的話,就會往上走,查找類中是不是存在name
就好像這樣的代碼:
class magic:
# def __init__(self,name):
# self.name = name
name = '浪子'
m = magic()
print(m.name)
print(magic.name)
傳回結果:
浪子
浪子
三大方法
python類的調用有三大方法,分别是類方法,靜态方法,執行個體方法。這三個方法在曾經的文章有說過。
Python面向對象程式設計
這裡就不多做代碼重寫,去原連結檢視學習即可。
資料封裝與私有屬性
私有屬性,也叫私有方法,是以雙下劃線開頭的命名變量。
無法通過執行個體方法和子類來調用的,隻能通過類中寫的方法來調用。
比如:
class magic:
__user = '浪子'
a = magic
print(magic.__user)
print(a.__user)
加了雙下劃線的user就是私有屬性,是沒法通過下面兩種方式進行調用的,唯一可以調用這個私有屬性的方法就是使用類方法。
class magic:
__user = '浪子'
@classmethod
def run(cls):
print(cls.__user)
magic.run()
隻有這樣才能調用類的私有屬性,這也就是對資料做了一個很好的封裝。
但是這樣的封裝并不是完全安全的,比如你看下面的代碼:
class magic:
__user = '浪子'
m = magic
print(m._magic__user)
這樣能直接調用user,說白了這是一個小技巧python把私有變量偷偷隐藏起來變成了這樣子。
python的自省機制
自省:通過一定的機制,查詢到對象的内部結構
使用__dict__方法查詢類的屬性:
class magic:
'我是注釋'
user = '浪子'
def run(age):
print(age)
for x,y in magic.__dict__.items():
print(x,':',y)
傳回結果:
__module__ : __main__
__doc__ : 我是注釋
user : 浪子
run : 0x0000018AB312CC80>
__dict__ : '__dict__' of 'magic' objects>
__weakref__ : '__weakref__' of 'magic' objects>
通過dict來擷取類的内部結果,記住通過magic.__dict__[‘user’]=’小桃紅’也可以動态操作屬性。
不僅僅是dict,通過dir可以更加強大的列出該類的所有屬性。
super函數
super函數,調用父類。在類的繼承中,如果重定義某個方法,該方法會覆寫父類的同名方法,但有時,我們希望能同時實作父類的功能,這時,我們就需要調用父類的方法了,可通過使用 super 來實作。
class A:
def __init__(self,name):
self.name = name
def run(self):
print(self.name+'6666666')
class B(A):
def __init__(self,name):
self.name = name
def run(self):
print(self.name+'7777777')
super().run()
#這裡是調用父類的run()方法
# 還可以這樣super().__init__(name=name)這樣的格式
c = B('浪子')
c.run()
傳回對象:
浪子7777777
浪子6666666
事實上,super 和父類沒有實質性的關聯,super(cls, inst) 獲得的是 cls 在 inst 的 MRO 清單中的下一個類。MRO則是python中類繼承關系選擇的一種,有點像是廣度優先原則,可以print m.__mro__檢視。
(完)
看完本文有收獲?請轉發分享給更多人
關注「Python那些事」,做全棧開發工程師
推薦閱讀
- 爬蟲非專業八級模拟考試
- 我們不再需要 Chrome 了?
- 為什麼Python不用設計模式?
- 用Python發一個高逼格的朋友圈