Python面向?qū)ο?/h1>
1.面向?qū)ο蠹夹g(shù)簡介
·? ? ? ?類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例(對象是類實例化之后的結(jié)果)。
·? ? ? ?類變量:類變量在整個實例化的對象中是公用的。類變量定義在類中且在函數(shù)體之外。類變量通常不作為實例變量使用。
·? ? ? ?數(shù)據(jù)成員:類變量或者實例變量用于處理類及其實例對象的相關(guān)的數(shù)據(jù)。
·? ? ? ?方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱為方法的重寫。
·? ? ? ?實例變量:定義在方法中的變量,只作用于當(dāng)前實例的類。
·? ? ? ?繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個派生類的對象作為一個基類對象對待。例如,有這樣一個設(shè)計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關(guān)系(例圖,Dog是一個Animal)。
·? ? ? ?實例化:創(chuàng)建一個類的實例,類的具體對象。
·? ? ? ?方法:類中定義的函數(shù)。
·? ? ? ?對象:通過類定義的數(shù)據(jù)結(jié)構(gòu)實例。對象包括兩個數(shù)據(jù)成員(類變量和實例變量)和方法。
2.創(chuàng)建類
?
'所有員工的基類'
class Employee:
? ? empCount = 0
? ? def __init__(self, name, salary): #構(gòu)造函數(shù)
? ? ? ? self.name = name? ? ? ? ? ? # 添加實例屬性
? ? ? ? self.salary = salary? ? ? ? # 添加實例屬性
? ? ? ? Employee.empCount += 1? ? ? # 修改類屬性
? ? def displayCount(self):? ? ? ? ?# 添加實例方法
? ? ? ? print("TotalEmployee %d" % Employee.empCount) # 讀取類屬性
?
? ? def displayEmployee(self):? ? ? # 添加實例方法
? ? ? ? print("Name:", self.name, ", Salary:", self.salary) # 讀取實例屬性
·? ? empCount變量是一個類變量,它的值將在這個類的所有實例之間共享。你可以在內(nèi)部類或外部類使用 Employee.empCount訪問。
·? ? ? ?第一種方法__init__()方法是一種特殊的方法,被稱為類的構(gòu)造函數(shù)或初始化方法,當(dāng)創(chuàng)建了這個類的實例時就會調(diào)用該方法
·? ? ? ?self代表類的實例,self在定義類的方法時是必須有的,雖然在調(diào)用時不必傳入相應(yīng)的參數(shù)。Self代表了一件事情,那就是:類的方法與普通的函數(shù)只有一個特別的區(qū)別——它們必須有一個額外的第一個參數(shù)名稱,按照慣例它的名稱是 self。
3.創(chuàng)建實例對象
實例化類其他編程語言中一般用關(guān)鍵字 new,但是在 Python中并沒有這個關(guān)鍵字,類的實例化類似函數(shù)調(diào)用方式。
以下使用類的名稱Employee 來實例化,并通過 __init__ 方法接受參數(shù)。
"創(chuàng)建 Employee類的第一個對象"
emp1 = Employee("Zara",2000)
"創(chuàng)建 Employee類的第二個對象"
emp2 = Employee("Manni",5000)
4.操作對象屬性
下面是讀取對象屬性的實例:
'所有員工的基類'
class Employee:
? ? empCount = 0
? ? def __init__(self, name, salary): #構(gòu)造函數(shù)
? ? ? ? self.name = name? ? ? ? ? ? # 添加實例屬性
? ? ? ? self.salary = salary? ? ? ? # 添加實例屬性
? ? ? ? Employee.empCount += 1? ? ? # 修改類屬性
? ? def displayCount(self):? ? ? ? ?# 添加實例方法
? ? ? ? print("TotalEmployee %d" % Employee.empCount) # 讀取類屬性
?
? ? def displayEmployee(self):? ? ? # 添加實例方法
? ? ? ? print("Name:", self.name, ", Salary:", self.salary) # 讀取實例屬性
?
?
# "創(chuàng)建 Employee 類的第一個對象"
emp1 =Employee("Zara",2000)
# "創(chuàng)建 Employee 類的第二個對象"
emp2 =Employee("Manni",5000)
emp1.displayEmployee()
emp2.displayEmployee()
print("TotalEmployee %d" %Employee.empCount)
以下函數(shù)還可以對屬性進行讀取之外的操作:
·? ? ? ?getattr(obj,name[, default]) :訪問對象的屬性。
·? ? ? ?hasattr(obj,name):檢查是否存在一個屬性。
·? ? ? ?setattr(obj,name,value):設(shè)置一個屬性。如果屬性不存在,會創(chuàng)建一個新屬性。
·? ? ? ?delattr(obj,name) :刪除屬性。
5.Python內(nèi)置的類屬性
·? ? ? ?__dict__ :類的屬性(包含一個字典,由類的數(shù)據(jù)屬性組成)
·? ? ? ?__doc__ :類的文檔字符串
·? ? ? ?__name__:類名
·? ? ? ?__module__:類定義所在的模塊(類的全名是'__main__.className',如果類位于一個導(dǎo)入模塊mymod中,那么className.__module__ 等于 mymod)
·? ? ? ?__bases__ :類的所有父類構(gòu)成元素(包含了一個由所有父類組成的元組)
6.類的繼承
面向?qū)ο蟮木幊處淼闹饕锰幹皇谴a的重用,實現(xiàn)這種重用的方法之一是通過繼承機制。繼承完全可以理解成類之間的類型和子類型關(guān)系。
在python中繼承中的一些特點:
·? ? ? ?1:在繼承中基類的構(gòu)造(__init__()方法)不會被自動調(diào)用,它需要在其派生類的構(gòu)造中親自專門調(diào)用。
·? ? ? ?2:在調(diào)用基類的方法時,需要加上基類的類名前綴,且需要帶上self參數(shù)變量。區(qū)別于在類中調(diào)用普通函數(shù)時并不需要帶上self參數(shù)
·? ? ? ?3:Python總是首先查找對應(yīng)類型的方法,如果它不能在派生類中找到對應(yīng)的方法,它才開始到基類中逐個查找。(先在本類中查找調(diào)用的方法,找不到才去基類中找)。
如果在繼承元組中列了一個以上的類,那么它就被稱作"多重繼承" 。
class Parent:
? ? # 定義父類
? ? parentAttr =100
? ? def __init__(self):
? ? ? ? print("調(diào)用父類構(gòu)造函數(shù)")
? ? def parentMethod(self):
? ? ? ? print('調(diào)用父類方法')
? ? def setAttr(self,attr):
? ? ? ? Parent.parentAttr =attr
? ? def getAttr(self):
? ? ? ? print("父類屬性 :",Parent.parentAttr)
?
class Child(Parent):
? ? # 定義子類
? ? def __init__(self):
? ? ? ? print("調(diào)用子類構(gòu)造方法")? #無論子類還是父類,都要單獨寫一次_init_
? ? def childMethod(self):
? ? ? ? print('調(diào)用子類方法')
? ? def getAttr (self):
? ? ? ? print('重寫父類方法,因為父類方法不能滿足需求')
?
c = Child()? #實例化子類
c.childMethod()#調(diào)用子類的方法
c.parentMethod()#調(diào)用父類方法
c.setAttr(200)? #再次調(diào)用父類的方法 -設(shè)置屬性值
c.getAttr()#再次調(diào)用父類的方法 -獲取屬性值
你可以使用issubclass()或者isinstance()方法來檢測,一個類或?qū)ο笫欠駷槠渌惢驅(qū)ο蟮淖宇悺?/p>
·? ? ? ?issubclass() -布爾函數(shù)判斷一個類是另一個類的子類或者子孫類,語法:issubclass(sub,sup)
·? ? ? ?isinstance(obj, Class)布爾函數(shù)如果obj是Class類的實例對象或者是一個Class子類的實例對象則返回true。
7.運算符重載
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)
以上代碼執(zhí)行結(jié)果如下所示:
Vector(7, 8)
8.類的私有屬性及方法
1)類的私有屬性
__private_attrs:兩個下劃線開頭,聲明該屬性為私有,不能在類的外部被使用或直接訪問。在類內(nèi)部的方法中使用是self.__private_attrs。
2)類的私有方法
__private_method:兩個下劃線開頭,聲明該方法為私有方法,不能在類地外部調(diào)用。在類的內(nèi)部調(diào)用self.__private_methods
3)實例
class JustCounter:
? ? __secretCount = 0
? ? # 私有變量
? ? publicCount = 0
? ? # 公開變量
? ? def count(self):
? ? ? ? self.__secretCount += 1
? ? ? ? self.publicCount += 1
? ? ? ? print(self.__secretCount)? # 在內(nèi)部使用私有化屬性,不會產(chǎn)生錯誤
?
counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)
print(counter.__secretCount)
# 報錯,實例不能訪問私有變量
9.單下劃線、雙下劃線、頭尾雙下劃線說明:
·? ? ? ?__foo__:定義的是特列方法,類似 __init__() 之類的。
·? ? ? ?_foo:以單下劃線開頭的表示的是 protected類型的變量,即保護類型只能允許其本身與子類進行訪問,不能用于 from module import *
·? ? ? ?__foo:雙下劃線的表示的是私有類型(private)的變量,只能是允許這個類本身進行訪問了。