您好,登錄后才能下訂單哦!
這篇文章主要介紹Python3.8類基礎語法的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
最簡單的類定義看起來像這樣:
class ClassName: <statement-1> . . . <statement-N>
類定義與函數定義 (def 語句) 一樣必須被執行才會起作用。
當進入類定義時,將創建一個新的命名空間,并將其用作局部作用域。因此,所有對局部變量的賦值都是在這個新命名空間之內。 特別的,函數定義會綁定到這里的新函數名稱。
類對象支持兩種操作:屬性引用和實例化。
(1)屬性引用
屬性引用的標準語法: obj.name
。
有效的屬性名稱是,類對象被創建時,存在于類命名空間中的所有名稱。 因此,如果類定義是這樣的:
class MyClass: """A simple example class""" i = 12345 def f(self): return 'hello world'
那么 MyClass.i
和 MyClass.f
就是有效的屬性引用,將分別返回一個整數和一個函數對象。
類屬性也可以被賦值,因此可以通過賦值來更改 MyClass.i
的值。
__doc__
也是一個有效的屬性,將返回所屬類的文檔字符串: "A simple example class"。
(2)實例化
類的實例化使用函數表示法。
可以把類對象視為是返回該類的一個新實例的不帶參數的函數。 舉例來說(假設使用上述的類):
x = MyClass()
創建類的新實例并將此對象分配給局部變量 x。
實例化操作(“調用”類對象)會創建一個空對象,也可以使用__init__()
創建帶有特定初始狀態的自定義實例。例如:
def __init__(self): self.data = []
此時,類的實例化操作會自動為新創建的類實例調用 __init__()
。 因此在這個示例中,可以通過 x = MyClass()
語句獲得一個經初始化的新實例:
__init__()
方法還可以有額外參數以實現更高靈活性。在這種情況下,提供給類實例化運算符的參數將被傳遞給 __init__()
。 例如,:
>>> class Complex: ... def __init__(self, realpart, imagpart): ... self.r = realpart ... self.i = imagpart ... >>> x = Complex(3.0, -4.5) >>> x.r, x.i (3.0, -4.5)
實例對象唯一操作是屬性引用。 有兩種有效的屬性名稱:數據屬性和方法。
(1)數據屬性
數據屬性不需要聲明,像局部變量一樣,它們將在第一次被賦值時產生。
例如,如果 x 是上面創建的 MyClass 的實例,則以下代碼段將打印數值 16,且不保留任何追蹤信息:
x.counter = 1 while x.counter < 10: x.counter = x.counter * 2 print(x.counter) del x.counter
(2)方法
方法是“從屬于”對象的函數。 【注:方法是針對對象來說的,函數是針對類來說的】
(在 Python 中,方法這個術語并不是類實例所特有的:其他對象也可以有方法。例如,列表對象具有 append, insert, remove, sort 等方法。然而,在以下討論中,我們使用方法一詞將專指類實例對象的方法,除非另外顯式地說明。)
實例對象的有效方法名稱依賴于其所屬的類。 【注:這里說的是方法名稱】
根據定義,一個類中所有是函數對象的屬性都是定義了其實例的相應方法。
因此在我們的示例中,x.f 是有效的方法引用,因為 MyClass.f 是一個函數,而 x.i 不是方法,因為 MyClass.i 不是一個函數。 但是x.f 與 MyClass.f 并不是一回事,它是一個方法對象,不是函數對象。
通常,方法在綁定后立即被調用,在 MyClass 示例中,這將返回字符串 'hello world'。
x.f()
但是,立即調用一個方法并不是必須的: x.f 是一個方法對象,它可以被保存起來以后再調用。 例如:
xf = x.f while True: print(xf())
將繼續打印 hello world,直到結束。
雖然 f()
的函數定義指定了一個參數,但在上面調用 x.f()
時并沒有帶參數。 當不帶參數地調用一個需要參數的函數時 Python 肯定會引發異常,即使參數實際未被使用。
方法的特殊之處就在于實例對象會作為函數的第一個參數被傳入。 在我們的示例中,調用 x.f() 其實就相當于 MyClass.f(x)。 【注:也就是方法參數列表中的self】
總之,調用一個具有 n 個參數的方法就相當于調用再多一個參數的對應函數,這個參數值為方法所屬實例對象,位置在其他參數之前。
當一個實例的非數據屬性【注:即方法】被引用時,將搜索實例所屬的類。
如果被引用的屬性名稱表示一個有效的類屬性中的函數對象,會通過打包(指向)查找到的實例對象和函數對象 到一個抽象對象的方式來創建方法對象:這個抽象對象就是方法對象。 【注:xf = x.f,x.f 是一個方法對象】
當附帶參數列表調用方法對象時,將基于實例對象和參數列表構建一個新的參數列表【注:self和參數列表】,并使用這個新參數列表調用相應的函數對象。
一般來說,實例變量用于每個實例的唯一數據,而類變量用于類的所有實例共享的屬性和方法:
【注:下例中kind
是類變量,name
是實例變量】
class Dog: kind = 'canine' # class variable shared by all instances def __init__(self, name): self.name = name # instance variable unique to each instance >>> d = Dog('Fido') >>> e = Dog('Buddy') >>> d.kind # shared by all dogs 'canine' >>> e.kind # shared by all dogs 'canine' >>> d.name # unique to d 'Fido' >>> e.name # unique to e 'Buddy'
正如 名稱和對象 中已討論過的,共享數據可能在涉及可變對象的時候,例如列表和字典,導致令人驚訝的結果。
例如以下代碼中的 tricks 列表不應該被用作類變量,因為所有的 Dog 實例將只共享一個單獨的列表:
【注:類變量是所有實例所共享的,以下代碼中的 tricks 列表不應該被用作類變量,實例調用 add_trick 時,就改變了 tricks 列表】
class Dog: tricks = [] # mistaken use of a class variable def __init__(self, name): self.name = name def add_trick(self, trick): self.tricks.append(trick) >>> d = Dog('Fido') >>> e = Dog('Buddy') >>> d.add_trick('roll over') >>> e.add_trick('play dead') >>> d.tricks # unexpectedly shared by all dogs ['roll over', 'play dead']
正確的類設計應該使用實例變量:
class Dog: def __init__(self, name): self.name = name self.tricks = [] # creates a new empty list for each dog def add_trick(self, trick): self.tricks.append(trick) >>> d = Dog('Fido') >>> e = Dog('Buddy') >>> d.add_trick('roll over') >>> e.add_trick('play dead') >>> d.tricks ['roll over'] >>> e.tricks ['play dead']
如果同樣的屬性名稱同時出現在實例和類中,則屬性查找會優先選擇實例:
>>> >>> class Warehouse: purpose = 'storage' region = 'west' >>> w1 = Warehouse() >>> print(w1.purpose, w1.region) storage west >>> w2 = Warehouse() >>> w2.region = 'east' >>> print(w2.purpose, w2.region) storage east
方法的第一個參數常常被命名為 self。 這也不過就是一個約定: self 這一名稱在 Python 中絕對沒有特殊含義。但是要注意,不遵循此約定會使得你的代碼對其他 Python 程序員來說缺乏可讀性,而且也可以想像一個 類瀏覽器 程序的編寫可能會依賴于這樣的約定。
任何一個作為類屬性的函數都為該類的實例定義了一個相應方法。 函數定義的文本并非必須包含于類定義之內:將一個函數對象賦值給一個局部變量也是可以的。 例如:
# Function defined outside the class def f1(self, x, y): return min(x, x+y) class C: f = f1 def g(self): return 'hello world' h = g
現在 f, g 和 h 都是 C 類的引用函數對象的屬性,因而它們就都是 C 的實例的方法,其中 h 完全等同于 g。 但請注意,本示例的做法通常只會令程序的閱讀者感到迷惑。
方法可以通過使用 self 參數的方法屬性調用其他方法:
class Bag: def __init__(self): self.data = [] def add(self, x): self.data.append(x) def addtwice(self, x): self.add(x) self.add(x)
方法可以通過與普通函數相同的方式引用全局名稱。與方法相關聯的全局作用域就是包含其定義的模塊。(類永遠不會被作為全局作用域。)
雖然我們很少會有充分的理由在方法中使用全局作用域,但全局作用域存在許多合法的使用場景:舉個例子,導入到全局作用域的函數和模塊可以被方法所使用,在其中定義的函數和類也一樣。
通常,包含該方法的類本身是在全局作用域中定義的,而在下一節中我們將會發現為何方法需要引用其所屬類的很好的理由。
每個值都是一個對象,因此具有 類(也稱為 類型),并存儲為 object.__class__
。
以上是“Python3.8類基礎語法的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。