如果你沒有任何以往的經驗與面向對象(OO)編程,你可能想諮詢或至少某種教程的入門課程,所以,你必須掌握的基本概念.
然而,這裏是小推出的面向對象編程(OOP)給你帶來更好的學習速度:
面向對象術語
類: 用戶定義的一個對象,它定義了一套類的任何對象的屬性特點的原型。屬性數據成員(類變量和實例變量)和方法,通過點符號訪問.
類變量: 一個類的所有實例共享變量。類變量被定義在一個類以外的任何類的方法。不作爲類變量經常作爲實例變量.
數據成員: A類變量或實例變量持有一個類和它的對象的相關數據.
函數重載: 分配到一個特定功能的多個行爲。執行的操作,因涉及的對象(參數)的類型。
實例變量: 一個方法內定義的變量只屬於一類的當前實例.
繼承 : 傳遞類的特點是從它派生的其他類.
實例: 某個類的一個單獨的對象。例如,一個對象obj屬於類Circle,是類Circle的一個實例.
實例化 : 創建一個類的實例.
方法 : 一個是定義在類定義中的一種特殊功能.
對象: 這是由它的類定義一個數據結構的一個唯一的實例。對象包括數據成員(類變量和實例變量)和方法.
運算符重載: 多個函數分配到一個特定的運算符.
創建類:
類的語句創建一個新的類定義。類名緊跟在class關鍵字,隨後由一個冒號如下:
class ClassName: 'Optional class documentation string' class_suite
-
類有一個文檔可以是通過ClassName.__doc__訪問的字符串.
-
該class_suite組成的所有組件的語句,定義類的成員,屬性數據和函數.
例子:
下面是一個簡單的Python類的例子:
class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
-
在的變量empCount是一個類變量,它的值將這個類的所有實例之間共享。這可以作爲Employee.empCount類或內部類的外部訪問.
-
第一種方法__init__()方法是一種特殊的方法,被稱爲類的構造函數或初始化方法,當你創建了這個類的新實例時Python就會調用.
-
你聲明異常,每個方法的第一個參數是自我的正常功能等其他類的方法。 Python中添加自參數到你的列表,當你調用的方法,你不需要包括它.
創建實例對象:
要創建一個類的實例,調用類,使用類的名稱,並通過在其__init__方法接受任何參數.
"This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000)
訪問屬性:
您可以使用點運算對象訪問對象的屬性。使用如下類的名稱將訪問類變量:
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
現在把它一起:
#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
這將產生以下結果:
Name : Zara ,Salary: 2000 Name : Manni ,Salary: 5000 Total Employee 2
在任何時候,您可以添加,刪除或修改類和對象的屬性:
emp1.age = 7 # Add an 'age' attribute. emp1.age = 8 # Modify 'age' attribute. del emp1.age # Delete 'age' attribute.
而不是使用正常的語句來訪問屬性,可以使用以下功能:
-
getattr(obj, name[, default]) : 訪問對象的屬性.
-
The hasattr(obj,name) : 檢查是否存在一個屬性.
-
The setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,然後將它創建.
-
The delattr(obj, name) : 刪除屬性.
hasattr(emp1, 'age') # Returns true if 'age' attribute exists getattr(emp1, 'age') # Returns value of 'age' attribute setattr(emp1, 'age', 8) # Set attribute 'age' at 8 delattr(empl, 'age') # Delete attribute 'age'
內建類屬性:
每個Python類繼內置屬性,他們可以使用點運算符像任何其他屬性:
-
__dict__ : 字典,包含類的命名空間.
-
__doc__ : 如果未定義類的文檔字符串,則沒有.
-
__name__: 類名.
-
__module__: 在類定義的模塊名稱。此屬性是“__main__”的交互模式.
-
__bases__ : 一個基類包含在其發生在基類列表中的順序可能是空的元組,.
對於上面的類,讓我們嘗試訪問所有這些屬性:
print "Employee.__doc__:", Employee.__doc__ print "Employee.__name__:", Employee.__name__ print "Employee.__module__:", Employee.__module__ print "Employee.__bases__:", Employee.__bases__ print "Employee.__dict__:", Employee.__dict__
這將產生以下結果:
Employee.__doc__: Common base class for all employees Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: () Employee.__dict__: {'__module__': '__main__', 'displayCount':, 'empCount': 2, 'displayEmployee':, '__doc__': 'Common base class for all employees', '__init__':}
銷燬對象(垃圾收集):
Python中刪除不必要的對象(內置類型或類的實例),自動釋放內存空間。其中Python的定期回收不再使用的內存塊的過程被稱爲垃圾收集.
Python的垃圾收集器運行程序執行過程中被觸發時,一個對象的引用計數達到零。別名對象的引用計數的變化,指出它的變化:
一個對象的引用計數增加時,它分配一個新的名稱或放置在一個容器(列表,元組或字典)。該對象的引用計數減少,其引用被重新分配,或者其引用超出範圍時,它用del刪除。當一個對象的引用計數達到零時,Python它會自動收集.
a = 40 # Create objectb = a # Increase ref. count ofc = [b] # Increase ref. count ofdel a # Decrease ref. count ofb = 100 # Decrease ref. count ofc[0] = -1 # Decrease ref. count of
你通常不會注意到,當垃圾收集器會破壞一個孤立的實例,並回收其空間。但是,一個類可以實現特殊方法__del__(),稱爲析構函數,實例是即將被銷燬時被調用。這種方法可用於任何一個實例的非內存資源用於清理.
例子:
__del__()析構函數打印一個實例的類的名稱,是即將被銷燬:
#!/usr/bin/python class Point: def __init( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts del pt1 del pt2 del pt3
這將產生以下結果:
3083401324 3083401324 3083401324 Point destroyed
注: 理想的情況下,你應該在單獨的文件中定義的類,那麼你應該在你的主程序文件使用import語句導入。 - 更多細節,請查看Python的導入模塊和類模塊章節.
類的繼承:
而非從頭開始,你可以創建一個類,它從一個已經存在的類派生新類的名稱後括號中的父類列出:
子類繼承它的父類的屬性,如果他們在子類中定義,你可以使用這些屬性。子類也可以覆蓋從父數據成員和方法.
語法:
派生類的聲明,就像他們的父類;但是繼承的基類列表類名後:
class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite
例子:
#!/usr/bin/python class Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttr class Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method' c = Child() # instance of child c.childMethod() # child calls its method c.parentMethod() # calls parent's method c.setAttr(200) # again call parent's method c.getAttr() # again call parent's method
這將產生以下結果:
Calling child constructor Calling child method Calling parent method Parent attribute : 200
類似的方式,你可以從多個父類的類如下:
class A: # define your class A ..... class B: # define your calss B ..... class C(A, B): # subclass of A and B .....
您可以使用issubclass()或isinstance()函數來檢查一個關係兩個類和實例:
-
issubclass(sub, sup) 布爾函數返回true,如果給定的子類subis的確是一個超類的子類sup.
-
isinstance(obj, Class) 布爾函數返回true,如果obj是一個Class類的實例,或者是一類的子類的一個實例.
重寫方法:
你總是可以覆蓋父類方法。覆蓋父方法的原因之一是因爲你可能想在你的子類特殊或不同的功能.
例如:
#!/usr/bin/python class Parent: # define parent class def myMethod(self): print 'Calling parent method' class Child(Parent): # define child class def myMethod(self): print 'Calling child method' c = Child() # instance of child c.myMethod() # child calls overridden method
這將產生以下結果:
Calling child method
相應重載方法:
下表列出了一些通用的功能,你可以在自己的類覆蓋:
SN | 方法、描述和簡單調用 |
---|---|
1 |
__init__ ( self [,args...] ) Constructor (with any optional arguments) Sample Call : obj = className(args) |
2 |
__del__( self ) Destructor, deletes an object Sample Call : dell obj |
3 |
__repr__( self ) Evaluatable string representation Sample Call : repr(obj) |
4 |
__str__( self ) Printable string representation Sample Call : str(obj) |
5 |
__cmp__ ( self, x ) Object comparison Sample Call : cmp(obj, x) |
重載操作符:
假設你已經創建了一個Vector類來表示二維向量。當您使用加運算,將它們添加,會發生什麼?最有可能的Python會罵你.
但是,你可以在類中定義__ add__方法進行向量相加,然後加上運算符將表現爲每個期望:
例子:
#!/usr/bin/python class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print v1 + v2
This would produce following result:
Vector(7,8)
Data Hiding:
An object's attributes may or may not be visible outside the class definition. For these cases, you can name attributes with a double underscore prefix, and those attributes will not be directly visible to outsiders:
Example:
#!/usr/bin/python class JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.__secretCount
結果如下:
1 2 Traceback (most recent call last): File "test.py", line 12, inprint counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'
你可以通過 object._className__attrName的形式來訪問.
如果你替換最後一行如下:
......................... print counter._JustCounter__secretCount
最終的結果將會是:
1 2 2