關於類(Class),是一個很抽象的概念。本篇幅簡單介紹關於類的一些基礎內容。更多深刻的內容,可詳閱官方文檔:html
https://docs.python.org/3/tutorial/index.htmlpython
在 Python 中,全部的數據類型均可以視爲對象,也能夠自定義對象。自定義對象數據類型就是類(Class)的概念。編程
Python 的類提供了面向對象編程的全部標準特性:類繼承機制容許多個基類,派生類能夠覆蓋基類的任何方法,一個方法能夠調用基類中相同名稱的方法。微信
最簡單的類定義的語法以下:app
class ClassName: <statement-1> . . . <statement-N>
類定義,和函數定義相似,必須定義執行後才能生效。函數
類對象支持兩種操做:屬性引用和實例化。設計
這裏的屬性引用使用的是 Python 中全部屬性引用的標準語法:obj.name
。有效的屬性名稱是類對象被建立存在於類命名空間的全部名稱。假設,類定義以下:code
class MyClass: """A simple example class""" i = 123 def func(self): return "hello world"
在這裏 MyClass.i
和 Myclass.func
屬於有效屬性,分別返回一個整數和一個函數對象。類屬性能夠被賦值,因此也能夠經過賦值改變 MyClass.i
的值。在這裏 __doc__
也是一個有效的屬性,它返回的是一個所屬類的文檔字符串:"A simple example class"
。htm
類的實例化使用函數表示法。例如,沿用上面的類:對象
x = MyClass()
建立類的實例,並將此對象賦值給變量 x。在這個實例化操做的過程當中,建立的是一個空對象。但許多類喜歡建立帶特定初始狀態的自定義實例。所以,一個類可以定義一個特殊的方法:__init__()
,例如:
def __init__(self): self.data = []
若是一個類定義了 __init__()
方法,建立新的實例的時候,會自動調用該方法。
固然,這個方法還可以有額外的參數。在這種狀況下,提供給類實例化的參數都會傳遞給 __init__()
,例如:
>>> class Student: ... def __init__(self, name, age): ... self.name = name ... self.age = age ... >>> s = Student('demon', 21) >>> s.name, s.age ('demon', 21)
從屬性引用來理解實例對象。兩種有效的屬性名稱包括:數據屬性和方法。
數據屬性不須要聲明:它會像局部變量同樣,在首次賦值的時候產生。
另外一種實例屬性引用稱爲方法。方法是從屬於對象的函數。(方法並不是類實例所特有的,其餘對象也有方法。本篇幅若無特別說明,方法一詞專指類實例對象的方法)
實例對象的有效方法名稱依賴於所屬的類。根據定義,一個類全部爲對象的屬性都定義了與實例的相應方法。
在上面自定義的 MyClass
類中,x.func
是有效的方法引用,由於 MyClass.func
是一個函數,而 x.i
並非方法,由於 MyClass.i
並非一個函數。但 x.func
並非就等同於 MyClass.func
,由於 x.func
是一個方法對象,不是函數對象。
在上面 MyClass
的例子中,執行下面的語句:
x.func()
這個時候回返回 hello world
。可是,當不想立刻就調用方法時,由於 x.func
是一個方法對象,能夠將其賦值給一個變量,等待後面調用。
xf = x.func print(xf())
當執行 print
語句時,一樣會返回 hello world
。
將前面的例子從新放到這裏:
class MyClass: """A simple example class""" i = 123 def func(self): return "hello world" x = MyClass()
在前面執行 x.func()
的時候,這裏並無帶參數,可是在 func 的函數定義時,指定了一個 self
參數。
這就是方法特殊的地方,實例對象會做爲函數的第一個參數被傳入。其實調用 x.func
等同於 MyClass.func(x)
。
通常來講,實例變量用於每一個實例的惟一數據,類變量用於類的全部實例共享的屬性和方法,以下實例:
class Dog: # 類變量,用於全部實例共享 kind = 'canine' def __init__(self, name): # 實例變量,每一個實例專有 self.name = name >>> d = Dog('Emy') >>> e = Dog('Buddy') >>> d.kind 'canine' >>> e.kind 'canine' >>> d.name 'Emy' >>> e.name 'Buddy'
由上面的例子能夠看出, kind
類變量是全部實例共有的,而實例變量 name
則是每一個實例獨有的。
須要注意的是,共享的數據如果涉及到可變對象,每每獲得的結果並非指望的結果。例如:
class Dog: tricks = [] def __init__(self, name): self.name = name def add_tricks(self, trick): self.tricks.append(trick) >>> d = Dog('Emy') >>> e = Dog('Buddy') >>> d.add_tricks('roll over') >>> e.add_tricks('play dead') >>> d.tricks ['roll over', 'play dead'] >>> e.tricks ['roll over', 'play dead']
在這裏能夠看出,列表不該該被用做類變量。正確的類設計應該使用實例變量:
class Dog: def __init__(self, name): self.name = name self.tricks = [] def add_tricks(self, trick): self.tricks.append(trick) >>> d = Dog('Emy') >>> e = Dog('Buddy') >>> d.add_tricks('roll over') >>> e.add_tricks('play dead') >>> d.tricks ['roll over'] >>> e.tricks ['play dead']
注意事項: 數據屬性會覆蓋具備相同名稱的方法屬性。如果程序當中的代碼量夠大,這種狀況頗有可能會發生。因此能夠作某些約定來最小化這種可能產生衝突的狀況。例如在屬性名稱前加一個下劃線,或者方法屬性用動詞來命名,名詞來命名數據屬性。
以上就是關於類(Class)的一部分基礎內容,後續會另開篇幅繼續介紹類的其餘相關內容。
歡迎關注微信公衆號《書所集錄》