標籤:als str 父類 lambda 自動 amp call 自己的 本地
物件導向的編程簡要概括就是將要處理的問題抽象為資料和操作的集合,用類對其進行封裝。其中資料和操作都稱為類的屬性,它們是一般是不變的。
對類進行執行個體化產生我們所說的對象,對象有自己的屬性。對象的屬性一般是個人化的,不同的對象可能具有不同的屬性。同一個類的所有對象都共用類的屬性。
對象屬性的尋找順序為:對象自身 --> 類 --> 類的祖先類
在python中一切皆對象。
以下我們討論python中類相關的概念和文法。
1、類的定義
class ClassName: <statement-1> . . . <statement-N>
- 類定義必須使用class關鍵字
- 類名最好使用大駝峰,如ClassName, 這是一種約定
- 當輸入類定義時,一個新的命名空間產生,在類中定義的所有本地變數都放入這個新的命名空間。
- 命名空間中的所有變數都是類的屬性。類屬性主要分為兩類,資料屬性(變數)和函數。
- 語句塊執行完成後,產生一個類對象綁定到ClassName。ClassName的範圍由它的定義的位置決定。
python中一切皆對象,類也是對象,它是type類的執行個體。可以用 obj.__class__來查看一個對象是由那個類執行個體化而來的。
類中可以使用任何合法的語句,不過實際應用中,主要是指派陳述式和函數定義。
2、類對象
下面的代碼定義了一個 Chinese 類:
class Chinese: """A sample example class""" nationality = ‘China‘ def display(self): print(self, ‘I am Chinese!‘, sep=‘, ‘)for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]): print(name, ‘==>‘, value)
類定義會產生一個新的命名空間,其中包含了所有在類本地定義的變數,也就是類的屬性。這些屬性可以在類的 __dict__屬性中查看,可以將其近似等價於類的命名空間。其中 __name__形式的屬性為特殊屬性。
print(type(Chinese.__dict__)) # <class ‘mappingproxy‘>for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]): print(name, ‘==>‘, value)# __dict__ ==> <attribute ‘__dict__‘ of ‘Chinese‘ objects># __doc__ ==> A sample example class# __module__ ==> __main__# __weakref__ ==> <attribute ‘__weakref__‘ of ‘Chinese‘ objects># display ==> <function Chinese.display at 0x1020759d8># nationality ==> China
- __dict__ 在類定義的時候自動產生。
- __doc__ 類定義的時候自動產生。值為類定義語句塊內第一行,類的文檔字串,由三引號引用。如果沒有值為None。
- __module__ 類定義所在的模組,自動添加的屬性。如果是正在執行的模組,值為 __main__
- __weakref__
- display 和 nationality 使用者定義屬性
python中屬性的引用都是通過obj.name 的形式,name為對象 obj 的屬性。類中的所有屬性都可以通過obj.name 的形式引用。比如該類的兩個使用者自訂屬性:資料屬性 nationality 和 函數 display:
print(Chinese.nationality) # Chinaprint(Chinese.display) # <function Chinese.display at 0x1021759d8>Chinese.display(1) # 1, I am Chinese!
通過類引用函數並對其進行調用,與普通的函數調用沒有差異。不過,在類中定義的函數一般是給執行個體使用的,不建議直接通過類引用,下面會進一步說明。
3、類執行個體化
類的執行個體化使用和函數調用類似的文法。
xm = Chinese()
上面的語句建立了一個新的Chinese類的執行個體,並將其賦值給 xm 變數。執行個體有自己的命名空間:
print(xm.__dict__) # {}
可以看到 xm.__dict__ 的傳回值是一個空字典,執行個體 xm沒有自己的屬性。可以直接通過 xm.name = ‘xiaoming‘ 的形式為執行個體添加屬性。也可以通過 del xm.name 刪除該屬性:
xm.name = ‘xiaoming‘print(xm.__dict__) # {‘name‘: ‘xiaoming‘}del xm.nameprint(xm.__dict__) # {}
如果類的所有執行個體都具有某些屬性,只是屬性的值不同,可以通過定義執行個體的初始化方法,在方法中為執行個體添加屬性。
3.1 初始化方法
類的執行個體化過程:
- 執行個體化出一個對象
- 自動調用特殊方法 __init__對產生的對象初始化。如果類中沒有定義會在父類(父類的概念之後說明)中尋找該方法。
我們稱__init__方法為執行個體的初始化方法。
一般在執行個體初始化方法中會定義執行個體的個人化屬性,這些屬性是執行個體私人的,可以通過執行個體的__dict__屬性查看。執行個體的屬性不會影響類的屬性,換句話說類不能引用執行個體的屬性。
下面是對Chinese類的擴充:
class Chinese: """A sample example class""" nationality = ‘China‘ def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def display(self): print(self, ‘I am Chinese!‘, sep=‘, ‘)xm = Chinese(‘xiaoming‘, 18, ‘male‘)print(xm.__dict__) # {‘name‘: ‘xiaoming‘, ‘gender‘: ‘male‘, ‘age‘: 18}print(Chinese.__dict__.keys())# dict_keys([‘__weakref__‘, ‘__module__‘, ‘__dict__‘, ‘__init__‘, ‘nationality‘, ‘display‘, ‘__doc__‘])
self指代引用該方法的執行個體(具體實現在4.1介紹),執行個體化操作的參數列表化傳遞給__init__方法,Chinese(‘xiaoming‘, 18, ‘male‘) --> xm.__init__(‘xiaoming‘, 18, ‘male‘)
3.2 執行個體的類
查看對象的類:
print(xm.__class__)print(type(xm))# <class ‘__main__.Chinese‘># <class ‘__main__.Chinese‘>
判斷一個對象是不是某個類的執行個體:isinstance(obj, ClassName)
print(isinstance(xm, Chinese))# True
4 執行個體
執行個體可以操作兩種屬性:資料屬性和方法
print(xm.name, xm.age, xm.gender, sep=‘, ‘) # xiaoming, 18, maleprint(xm.nationality, xm.display, sep=‘, ‘) # China, <bound method Chinese.display of <__main__.Chinese object at 0x10217c898>>
有上面的代碼可以看到執行個體不僅可以引用自己的屬性,也可以引用類的屬性。類屬性可以被它的執行個體共用。
值得注意的是,執行個體對類的函數的引用。其傳回值並不是一個函數對象而是一個"bound method"綁定的方法對象。嘗試調用這個對象:
1 xm.display(1)2 # Traceback (most recent call last):3 # File "test.py", line 28, in <module>4 # xm.display(1)5 # TypeError: display() takes 1 positional argument but 2 were given6 xm.display() # <__main__.Chinese object at 0x10217c7f0>, I am Chinese!
display函數要求傳入一個位置參數,第1行給方法傳入一個參數1,調用出錯,錯誤資訊告訴我們多傳入了一個位置參數。
再次調用,不傳參,竟然能夠正常調用了!why?函數列印了傳入的值,"<__main__.Chinese object at 0x10217c7f0>",表明出入的是一個Chinese對象,在本例中只能是 xm。這是怎麼實現的呢?
4.1 執行個體方法
print(Chinese.display)print(xm.display)print(Chinese.display is xm.display)# <function Chinese.display at 0x1021759d8># <bound method Chinese.display of <__main__.Chinese object at 0x10217c7f0>># False
分別通過類和執行個體引用display屬性,返回的並不是同一個對象:通過類引用返回一個函數對象;通過執行個體引用返回一個"bound method"綁定的方法對象。
簡要概括來說就是,方法的第一個參數由python自動填滿以引用執行個體對象。
以上是相關的基本概念,下一篇討論類的封裝、繼承相關的概念。
python物件導向編程 -- 基本概念(python3.5)