使用者:Xyy23330121/Python/類
定義類
編輯使用 class
語句,我們可以定義一個類。
class ClassName: pass
這就定義了一個名為 ClassName
的類。與函數相似,「類」自身也是一個對象,支持一切一般對象的操作。
類的屬性
編輯類的屬性可以理解為是定義在類中的、特殊的變量。
定義了「類」之後,我們可以在class
子句給類添加屬性。也可以在定義後再添加屬性,比如:
class MyClass:
attr1 = 1
attr2 = "Two"
print(MyClass.attr1) #调用了 MyClass 的属性 attr1。输出:1
print(MyClass.attr2) #调用了 MyClass 的属性 attr2。输出:Two
MyClass.attr3 = "Third"
print(MyClass.attr3) #调用了 MyClass 的属性 attr3。输出:Third
如上述例子所述。我們可以通過 ClassName.AttrName
的方式調用類的屬性。其中 ClassName
指的是類的名稱,AttrName
指的是屬性的名稱
類似,我們可以在類中定義函數。類中的函數和其它函數在表現上毫無區別,只是在使用時需要在前面添加類的名稱罷了。
實例
編輯實例是類的一個重要組成部分。比如 1
是類型 int
的一個實例對象。我們創建的類型也可以有實例。
創建實例對象
編輯我們可以用 ClassName()
的方法創建實例。
class MyClass1:
a = 0
def Method1(self):
print(self.a, "调用了方法")
a = MyClass1()
print(a.a) #输出:0
a.Method1() #输出:0 调用了方法
__init__方法
編輯如果在類中定義了一個特殊的方法 __init__
我們就可以更靈活地創建實例。我們看以下示例:
class MyClass2:
def __init__(self, arg):
self.arg = arg
a = MyClass3("实例属性")
print(a.arg) #输出:实例属性
在調用 MyClass2()
的時候,我們創建了一個實例,然後把傳入 MyClass2()
的參數傳入到實例的 __init__
方法中。這個實例是 MyClass2
的實例,它在初始化時具有屬性 arg = "实例属性"
。
實例屬性與其作用域
編輯在類中定義的屬性或方法,在實例中也可以使用。我們看以下示例:
class attr:
n = 0
number = 0
array = []
def __init__(self,arg):
number = 1
array.append(arg)
a = attr("First")
b = attr("Second")
print(attr.n, attr.number, attr.array) #输出:0 0 ['First', 'Second']
print(a.n, a.number, a.array) #输出:0 1 ['First', 'Second']
print(b.n, b.number, b.array) #输出:0 1 ['First', 'Second']
可以看出,實例和函數類似。如果在實例中對可變對象的屬性作「直接賦值以外的更改操作」,則更改操作會影響到類的屬性。但對不可變對象的屬性,唯一的更改方式是賦值。此時,該屬性在實例作用域裡,而非類作用域裡。
實例的方法
編輯在類中定義的函數,在實例中也可以使用。此時稱該函數是一個「方法」。類中的函數在使用時和其它函數沒有區別,但是實例的方法不同。在調用實例的方法時,自動傳入的第一個參數的會是實例自身。比如:
class attr:
n = 0
number = 0
array = []
def __init__(self,arg):
number = 1
array.append(arg)
def prt(s):
print(s.n, s.number, s.array)
a = attr("First")
b = attr("Second")
attr.prt() #输出:0 0 ['First', 'Second']
a.prt() #输出:0 1 ['First', 'Second']
b.prt() #输出:0 1 ['First', 'Second']
可以看出,它正確傳入了實例,並在可能的條件下使用了實例的屬性。而沒有使用類的屬性。
裝飾器
編輯我們在之前學習函數時,學習過裝飾器相關的知識。到了本章節,有兩個好用的裝飾器可以使用。
classmethod
編輯該裝飾器用於類方法。與一般的方法傳入的是實例本身不同,類方法自動傳入的第一個參數是實例所屬的「類」。我們可以從以下示例中看出這一點:
class C:
isCls = True
def __init__(self):
self.isCls = False
def f(s):
print(s.isCls)
@classmethod
def g(s):
print(s.isCls)
a = C()
a.f() #输出:False
a.g() #输出:True
如同在裝飾器中提到的一樣,以上類等同於:
class C:
isCls = True
def __init__(self): self.isCls = False
def f(s): print(s.isCls)
g = classmethod(lambda s: print(s.isCls))
staticmethod
編輯該裝飾器用於靜態方法。靜態方法不會受類或實例改動的影響,它和函數的表現完全一致。
class C:
@staticmethod
def f(arg1, arg2):
print(arg1, arg2)
a = C()
a.f(0,1) #输出:0 1
C.f(0,1) #输出:0 1
可以看出,此時使用的方法「不會」自動傳入實例自身。這是因為調用裝飾器後,裝飾器返回的結果,會跳過自動傳入的第一個參數,從第二個參數開始處理。
同樣,以上的類等同於:
class C:
f = staticmethod(lambda x,y: print(x,y))
類相關的注釋
編輯文檔字符串
編輯類似函數注釋。對於類,或實例的方法,我們也可以使用文檔字符串。
class ClassWithDoc:
'''文档字符串'''
def MethodWithDoc():
'''文档字符串'''
pass
print(ClassWithDoc.__doc__)
a = ClassWithDoc()
print(a.MethodWithDoc.__doc__)
類型注釋
編輯在類中定義函數時,也可以使用類型注釋。