Python之類(Class)的學習

定義

Python 的 Class 比較特別,和我們習慣的靜態語言類型定義有很大區別。

1. 使用一個名爲 __init__ 的方法來完成初始化。
2. 使用一個名爲 __del__ 的方法來完成類似析購操作。
3. 所有的實例方法都擁有一個 self 參數來傳遞當前實例,類似於 this。
4. 可以使用 __class__ 來訪問類型成員

>>>>>> class MyClass: 
def __init__(self): 
print "initialize." 
def Foo(self): 
print id(self) 

>>>>>> a = MyClass() 
initialize
>>>>>> a.Foo() 
14412576 
>>>>>> id(a) 
14412576
 

 

Class 有一些特殊的屬性,便於我們獲得一些額外的信息。

>>>>>> class MyClass(object): 
"""This is MyClass's Docoment""" 
def __init__(self): 
self.i 
= 1234 
>>>>>> MyClass.__doc__ # 類型幫助信息 
"This is MyClass's Docoment""This is MyClass's Docoment" 
>>>>>> MyClass.__name__ # 類型名稱 
'MyClass' 
>>>>>> MyClass.__module__ # 類型所在模塊 
'__main__' 
>>>>>> MyClass.__bases__ # 類型所繼承的基類(Python 支持多繼承) 
(<type 'object'>,) 
>>>>>> MyClass.__dict__ # 類型字典,存儲所有類型成員信息 
<dictproxy object at 0x00DC1AD0> 
>>>>>> #以下是實例擁有的屬性 
>>>>>> MyClass().__class__ # 實例的類型 
<class '__main__.MyClass'> 
>>>>>> MyClass().__module__ # 實例類型所在模塊 
'__main__' 
>>>>>> MyClass().__dict__ # 對象字典,存儲所有實例成員信息 
{'i'1234
>>>>>>
 

 

繼承


Python 支持多繼承,但有幾點需要注意:

1. 基類 __init__ / __del__ 需顯示調用。
2. 繼承方法的調用和基類聲明順序有關。
>>>>>> class Base1: 
def __init__(self): 
print "Base1" 
def test(self): 
print "Base1 test" 


>>>>>> class Base2: 
def __init__(self): 
print "Base2" 
def test(self): 
print "Base2 test" 

>>>>>> class MyClass(Base2,Base1): 
def __init__(self): 
Base1.
__init__(self) 
Base2.
__init__(self) 
print "MyClass" 
>>>>>> a = MyClass() 
Base1 
Base2 
MyClass 
>>>>>> a.test() 
Base2 test 
>>>>>> # 下面把 Base1 放在前面 
>>>>>> class MyClass(Base1,Base2): 
def __init__(self): 
Base1.
__init__(self) 
Base2.
__init__(self) 
print "MyClass" 
>>>>>> a = MyClass() 
Base1 
Base2 
MyClass 
>>>>>> a.test() 
Base1 test 
>>>>>>
 

 

成員

Python Class 同樣包含類型和實例兩種成員。
>>>>>> class Class1: 
= 123 # 類成員 
def __init__(self): 
self.i 
= 100 # 實例成員 


>>>>>> print Class1.i 
123 
>>>>>> print Class1().i 
100 
>>>>>>
 

 

有幾個很 "特殊" 的 "規則" 需要注意。

(1) 我們可以通過實例引用訪問類型成員。因此下面的例子中 self.i 實際指向 Class1.i,直到我們爲實例新增了一個成員 i。

>>>>>> class Class1: 
= 123 
def __init__(self): 
print self.i 
print hex(id(self.i)) 

>>>>>> hex(id(Class1.i)) # 顯示 Class1.i 的地址 
'0xab5860' 
>>>>>> a = Class1() # 創建 Class1 實例,我們會發現 self.i 實際指向 Class1.i 
123 
0xab5860 
>>>>>> Class1.__dict__ # 顯示 Class1 成員 
{'i'123'__module__''__main__''__doc__': None, '__init__'<function __init__ at 0x012911B0>
>>>>>> a.__dict__ # 顯示實例成員 
{} 
>>>>>> a.i = 100 # 爲實例新增加一個成員i 
>>>>>> hex(id(a.i)) # 顯示新成員i的地址 
'0xab5974' 
>>>>>> a.__dict__ # 顯示實例成員 
{'i'100
>>>>>>

(2) 調用類型內部方法,需要省略 self 參數。

>>>>>> class Class1: 
def __init__(self): 
self.
__test("Hello Python"
def __test(self, s): 
print s 
>>>>>> Class1() 
Hello Python 
<__main__.Class1 instance at 0x00DC3800> 
>>>>>>

我們可以在成員名稱前添加 "__" 使其成爲私有成員。

>>>>>> class Class1: 
__i = 123 
def __init__(self): 
self.
__x = 0 
def __test(self): 
print id(self) 
>>>>>> Class1.i 

Traceback (most recent call last): 
File 
"<pyshell#203>", line 1in <module> 
Class1.i 
AttributeError: 
class Class1 has no attribute 'i' 
>>>>>> Class1().__x 

Traceback (most recent call last): 
File 
"<pyshell#204>", line 1in <module> 
Class1().
__x 
AttributeError: Class1 instance has no attribute 
'__x' 
>>>>>> Class1().__test() 

Traceback (most recent call last): 
File 
"<pyshell#205>", line 1in <module> 
Class1().
__test() 
AttributeError: Class1 instance has no attribute 
'__test' 
>>>>>>

事實上這只是一種規則,並不是編譯器上的限制。我們依然可以用特殊的語法來訪問私有成員。

>>>>>> Class1._Class1__i 
123 
>>>>>> a = Class1() 
>>>>>> a._Class1__x 

>>>>>> a._Class1__test() 
14432256 
>>>>>>

除了靜態(類型)字段,我們還可以定義靜態方法。

>>>>>> class Class1: 
@staticmethod 
def test(): 
print "In Static method" 
>>>>>> Class1.test() 
In Static method 
>>>>>>

從設計的角度,或許更希望用屬性(property)來代替字段(field)。

>>>>>> class Class1: 
def __init__(self): 
self.
__i = 1234 
def getI(self): return self.__i 
def setI(self, value): self.__i = value 
def delI(self): del self.__i 
= property(getI, setI, delI, "Property I"

>>>>>> a = Class1() 
>>>>>> a.I 
1234 
>>>>>> a.I = 1000 
>>>>>> a.I 
1000 

如果只是 readonly property,還可以用另外一種方式。

>>>>>> class Class1: 
def __init__(self): 
self.
__i = 1234 
@property 
def I(self): 
return self.__i 
>>>>>> a = Class1() 
>>>>>> a.I 
1234 

用 __getitem__ 和 __setitem__ 可以實現 C# 索引器的功能。

>>>>>> class Class1: 
def __init__(self): 
self.
__x = ["a""b""c"
def __getitem__(self, key): 
return self.__x[key] 
def __setitem__(self, key, value): 
self.
__x[key] = value 

>>>>>> a = Class1() 
>>>>>> a[1
'b' 
>>>>>> a[1= "xxx" 
>>>>>> a[1
'xxx' 
>>>>>>
 
發佈了113 篇原創文章 · 獲贊 93 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章