示例:app
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word)
其中 country 是類屬性,即 Person類 的靜態屬性,speak() 爲 Person類的函數屬性,即類的動態屬性~ide
對上述示例的類進行實例化:函數
>>> p = Person('Kitty', 18) # 實例化 Person類,獲得對象 p >>> p.name # 調用對象 p 的name屬性 'Kitty' >>> p.speak('hello') # 調用對象 p 的綁定方法 hello
類中的 __init__ 方法用於初始化對象,而在類的是實例化過程當中,對應類中第一個被調用的並非 __init__ 方法,第一個被調用的是 __new__方法。在對象的初始化以前首先要建立對象,__new__方法正是用來建立這個對象~
類的實例化過程也能夠經過以下語句來實現:.net
>>> p = object.__new__(Person) # __new__方法繼承自 object類 >>> Person.__init__(p, 'Kitty', 18) >>> p.name 'Kitty'
在Person類中重寫 __new__方法:code
class Person: country = "China" def __new__(cls, name, age): print('__new__ called') return super(Person, cls).__new__(cls) def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) p = Person('Kitty', 18) # 實例化對象 print('name : %s' % p.name) # 輸出結果: __new__ called name : Kitty
很明顯 __new__方法 是先於 __init__ 方法被調用的~
類的實例化過程大體步驟以下:
一、p = Person('Kitty', 18) ,會調用 Person類的__new__方法,並傳遞 name 和 age 參數
二、__new__方法 會建立一個 Person類的對象並返回
三、最後利用這個對象調用類的 __init__ 方法 完成初始化,__init__ 方法的第一個參數是self,對象在調用 __init__ 方法時會將本身當作參數傳遞給 這個self。
注意:__init__方法沒有返回值~,__init__ 方法僅完成對象的初始化工做~
對象
self是什麼?
在類的內部,self 就是一個對象。使用對象調用方法時(對象的綁定方法),當前對象會被自動傳遞給 self,即 self 表示調用該方法的對象~blog
操做類的變量屬性:繼承
>>> Person.country # 調用類屬性 'China' >>> Person.country = 'USA' # 修改類屬性 >>> Person.country 'USA' >>> del Person.country # 刪除類屬性 >>> Person.country # 刪除後沒法再調用 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'Person' has no attribute 'country'
調用類的函數屬性:
這裏僅介紹綁定方法的調用(即第一個參數是self的方法),類中的其餘方法暫先不作介紹~
speak() 是類的函數屬性,對象調用不須要傳遞 self參數(對象調用 會自動完成self參數傳值,下面會介紹),如果類來調用,則須要手動傳遞這個 self參數,即須要傳遞一個Person類的對象~ip
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) p = Person('Kitty', 18) p.speak('hello') # 對象調用,會自動將 對象p 做爲第一個參數傳遞給 self Person.speak(p, '你好') # 類調用須要手動傳遞 self 的值 # 輸出結果: hello 你好
類名.__dict__ 用來查看一個類(或對象)的名稱空間,能夠這樣理解。其實__dict__是類的一個內置屬性,存儲全部實例共享的變量和函數(類屬性,方法等),類的__dict__並不包含其父類的屬性。對象中的 __dict__ 屬性下面會介紹~
這裏注意和 dir() 方法的區別,dir(類名或對象名) 會返回一個類(或對象)的全部屬性,包括從父類中繼承的屬性。內存
Person類的__dict__屬性 {'__module__': '__main__', # 所處模塊 '__init__': <function Person.__init__ at 0x11023b378>, # __init__方法 'speak': <function Person.speak at 0x11023b400>, # speak 方法 '__dict__': <attribute '__dict__' of 'Person' objects>, # 應該就是指 類的__dict__屬性,具體參閱:https://blog.csdn.net/lis_12/article/details/53519060 '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} # # class說明文檔
調用類的屬性,首先會去類的名稱空間中(Person.__dict__)尋找對應名稱的key,至關於Person.__dict__['country'],也能夠直接這樣調用:
>>> Person.__dict__['country'] 'China' >>> Person.__dict__['country'] = 'USA' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'mappingproxy' object does not support item assignment
注意:
__dict__ 對於類中的屬性只能查看,不能修改~
除了 __dict__,Python中的類還有不少別的內置屬性:
__doc__ :類的說明
__name__: 類名
__module__: 類定義所在的模塊
__bases__ : 包含了類的全部父類 的元組
示例以下:
class Person: '''human being''' country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) print(Person.__doc__) print(Person.__name__) print(Person.__module__) print(Person.__bases__) #結果輸出: human being Person __main__ (<class 'object'>,)
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word)
實例化一個Person類的對象 的過程當中,init方法會將參數賦值給 name 與 age 屬性,能夠經過 實例的__dict__ 查看,注意:實例的__dict__ 僅存儲與該實例相關的實例屬性,沒有函數屬性,也沒有共有屬性~
>>> p = Person('Kitty', 18) >>> print(p.__dict__) {'name': 'Kitty', 'age': 18}
注意 實例.__dict__ 與 類.__dict__ 的區別~
經過 類.__dict__ 能夠查看類中的屬性,可是不能修改,可是經過 實例.__dict__ 除了查看,還能夠進行修改~
>>> p.__dict__['name'] 'Kitty' >>> p.__dict__['age'] 18 >>> p.__dict__['name'] = 'abc' >>> p.__dict__['age'] = 20 >>> p.name 'abc' >>> p.age 20
經過對象能夠直接調用該對象的變量屬性,例如 p對象 的 name屬性 和 age屬性~
>>> p = Person('Kitty', 18) >>> p.name 'Kitty' >>> p.age 18
也能夠經過 p對象 調用對應類(這裏是Person類)的變量屬性,如果類的變量屬性發生變化,則全部對象獲取到的類變量屬性都會改變~
>>> p.country 'China' >>> Person.country = 'UK' # 修改 類的變量屬性 >>> p2 = Person('baby', 22) >>> p.country 'UK' >>> p2.country 'UK'
Tip:
注意1
在修改類的變量屬性時,若變量是不可變類型,則僅能經過 類名.變量屬性 來修改,以下示例:
>>> Person.country = 'USA' # 修改類屬性 >>> p.country 'USA' >>> p.country = 'UK' >>> p.country 'UK' >>> Person.country 'USA' >>> p2.country 'USA'
p.country 並無修改類屬性,而是給本身添加了一個新的屬性,這個新添加的屬性存放在對象本身的名稱空間中,類的變量屬性 country 並無發生改變~
>>> p.__dict__ {'country': 'UK', 'age': 20, 'name': 'abc'}
在類中 self 表示當前調用的對象,當 self 引用的變量和類變量同名的時候,須要注意區分:這兩個變量之間沒有關聯,self 引用的變量屬於對象,放在對象的名稱空間中,類變量則放在類名稱空間中
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age self.country = 'AUS' # 添加對象屬性 def speak(self): print(self.country) ############ >>> p = Person('Kitty', 18) >>> p.country 'AUS' >>> p.speak() AUS >>> Person.country 'China'
注意2
當類變量爲可變類型時,須要區分對象的 2種 操做:
class Person: country = "China" lst = [] def __init__(self, name, age): self.name = name self.age = age self.lst.append(name) def speak(self): print(self.name) ############ >>> p = Person('Kitty', 18) >>> p.__dict__ {'age': 18, 'name': 'Kitty'} >>> Person.lst ['Kitty']
上述示例中,self 針對 lst 變量並非一個賦值操做,而是調用了 lst的append方法,因此這個過程會先在對象的名稱空間中尋找 lst 屬性,對象的名稱空間中沒有,而後再去類的名稱空間中尋找,Person類中存在該屬性,因而調用其 append 方法。
這個過程經過對象修改了類的可變類型的變量~
若 self 針對 lst 變量是一個賦值操做,這樣就爲當前對象新增了一個 lst 屬性
class Person: country = "China" lst = [] def __init__(self, name, age): self.name = name self.age = age self.lst = name def speak(self): print(self.name) ############ >>> p = Person('Kitty', 18) >>> p.__dict__ {'age': 18, 'name': 'Kitty', 'lst': 'Kitty'} >>> Person.__dict__ {'__module__': '__main__', 'country': 'China', 'lst': [], '__doc__': None, '__init__': <function __init__ at 0x105f5fc08>, 'speak': <function speak at 0x105f5c0c8>}
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self): print(self.name + ', ' + str(self.age)) ############ >>> p1 = Person('Kitty', 18) >>> p2 = Person('baby', 22) >>> p1.__dict__ {'age': 18, 'name': 'Kitty'} >>> p2.__dict__ {'age': 22, 'name': 'baby'}
能夠看到對象的名稱空間中沒有函數屬性,函數屬性在類的名稱空間當中
>>> Person.speak <unbound method Person.speak> >>> p1.speak <bound method Person.speak of <__main__.Person instance at 0x105f727a0>> >>> p2.speak <bound method Person.speak of <__main__.Person instance at 0x105f728c0>>
p1 和 p2 的 speak 方法爲綁定方法(bound method),且 p1 和 p2 的 speak 方法內存地址不一致,這兩個對象的 speak 方法都執行 類中對應的方法。
綁定方法,有兩種:綁定到類的方法和綁定到對象的方法,上述示例中的方法爲後者,綁定到對象的方法爲對象專門定製,使用對象調用的時候,會自動將 當前對象傳遞給方法的第一個參數(self,通常都叫self,也能夠寫成別的名稱),若使用類調用,則第一個參數須要手動傳值~
>>> p1.speak() Kitty, 18 >>> p2.speak() baby, 22 >>> Person.speak(p1) # 經過類調用 Kitty, 18
這裏僅對綁定到對象的方法作簡單介紹,類中還有綁定到類的方法,還有非綁定方法等...,以後會介紹
.................^_^