Python 類(Class)

類(Class)


關於類(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.iMyclass.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)的一部分基礎內容,後續會另開篇幅繼續介紹類的其餘相關內容。

歡迎關注微信公衆號《書所集錄》
相關文章
相關標籤/搜索