面向對象的編程帶來的主要好處之一是代碼的重用,實現這種重用的方法之一是通過繼承機制.
通過繼承創建的新類稱為子類或派生類,被繼承的類稱為基類、父類或超類.
繼承語法
class 派生類名(基類名)
...
在python中繼承中的一些特點:
如果在繼承元組中列了一個以上的類,那麼它就被稱作"多重繼承" .
語法:
派生類的聲明,與他們的父類類似,繼承的基類列表跟在類名之後,如下所示:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
視頻學習:Python面向對象提升與收發郵件_哔哩哔哩_bilibili P2
參考: Python中的多態如何理解?_tigerlib的博客-CSDN博客_python多態
多態的作用:讓具有不同功能的函數可以使用相同的函數名,這樣就可以用一個函數名調用不同內容(功能)的函數.
多態的特點:
1、只關心對象的實例方法是否同名,不關心對象所屬的類型;
2、對象所屬的類之間,繼承關系可有可無;
3、多態的好處可以增加代碼的外部調用靈活度,讓代碼更加通用,兼容性比較強;
4、多態是調用方法的技巧,不會影響到類的內部設計.
1. 對象所屬的類之間沒有繼承關系
調用同一個函數fly()
, 傳入不同的參數(對象),可以達成不同的功能
class Duck(object): # 鴨子類
def fly(self):
print("鴨子沿著地面飛起來了")
class Swan(object): # 天鵝類
def fly(self):
print("天鵝在空中翱翔")
class Plane(object): # 飛機類
def fly(self):
print("飛機隆隆地起飛了")
def fly(obj): # 實現飛的功能函數
obj.fly()
duck = Duck()
fly(duck)
swan = Swan()
fly(swan)
plane = Plane()
fly(plane)
===運行結果:===================================================================================
鴨子沿著地面飛起來了
天鵝在空中翱翔
飛機隆隆地起飛了
2. 對象所屬的類之間有繼承關系(應用更廣)
class gradapa(object):
def __init__(self,money):
self.money = money
def p(self):
print("this is gradapa")
class father(gradapa):
def __init__(self,money,job):
super().__init__(money)
self.job = job
def p(self):
print("this is father,我重寫了父類的方法")
class mother(gradapa):
def __init__(self, money, job):
super().__init__(money)
self.job = job
def p(self):
print("this is mother,我重寫了父類的方法")
return 100
#定義一個函數,函數調用類中的p()方法
def fc(obj):
obj.p()
gradapa1 = gradapa(3000)
father1 = father(2000,"工人")
mother1 = mother(1000,"老師")
fc(gradapa1) #這裡的多態性體現是向同一個函數,傳遞不同參數後,可以實現不同功能.
fc(father1)
print(fc(mother1))
===運行結果:===================================================================================
this is gradapa
this is father,我重寫了父類的方法
this is mother,我重寫了父類的方法
100
類屬性:A property to call with the class name
對象屬性:對象來調用
對象屬性的優先級高於類屬性(If the class attribute and object attribute have the same name,Then call the object properties)
Adding properties to object properties only takes effect on the current object,對於類創建的其他對象沒有作用
Class properties do not have the same name as object properties,因為對象屬性會屏蔽掉類屬性.But when removing the object property,Class properties can then be displayed when used
文檔地址:Python 面向對象 | 菜鳥教程
使用 class 語句來創建一個新類,class 之後為類的名稱並以冒號結尾:
class ClassName:
'類的幫助信息' #類文檔字符串
class_suite #類體
類的幫助信息可以通過ClassName.__doc__查看.
class_suite 由類成員,方法,數據屬性組成.
以下是一個簡單的 Python 類的例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Employee:
'所有員工的基類'
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__()方法是一種特殊的方法,被稱為類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法
self 代表類的實例,self 在定義類的方法時是必須有的,雖然在調用時不必傳入相應的參數.
類的方法與普通的函數只有一個特別的區別——它們必須有一個額外的第一個參數名稱, 按照慣例它的名稱是 self.
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
----------------------------------------------------------------------------------------
運算結果
<__main__.Test instance at 0x10d066878>
__main__.Test
從執行結果可以很明顯的看出,self 代表的是類的實例,代表當前對象的地址,而 self.__class__ 則指向類.
self 不是 python 關鍵字,我們把他換成 runoob 也是可以正常執行的:
class ClassName:
'類的幫助信息' #類文檔字符串
class_suite #類體
類的幫助信息可以通過ClassName.__doc__查看.
class_suite 由類成員,方法,數據屬性組成.
如果你的父類方法的功能不能滿足你的需求,你可以在子類重寫你父類的方法:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Parent: # 定義父類
def myMethod(self):
print '調用父類方法'
class Child(Parent): # 定義子類
def myMethod(self):
print '調用子類方法'
c = Child() # 子類實例
c.myMethod() # 子類調用重寫方法
-------------------------------------------------------------------------------------------
輸出結果
調用子類方法
Python同樣支持運算符重載,實例如下:
#!/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
-----------------------------------------------------------------------------------------
輸出結果
Vector(7,8)
實例化類其他編程語言中一般用關鍵字 new,但是在 Python 中並沒有這個關鍵字,類的實例化類似函數調用方式.
以下使用類的名稱 Employee 來實例化,並通過 __init__ 方法接收參數.
"創建 Employee 類的第一個對象"
emp1 = Employee("Zara", 2000)
"創建 Employee 類的第二個對象"
emp2 = Employee("Manni", 5000)
您可以使用點號 . 來訪問對象的屬性.使用如下類的名稱訪問類變量:
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
完整實例
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Employee:
'所有員工的基類'
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
"創建 Employee 類的第一個對象"
emp1 = Employee("Zara", 2000)
"創建 Employee 類的第二個對象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
你也可以使用以下函數的方式來訪問屬性:
hasattr(emp1, 'age') # 如果存在 'age' 屬性返回 True.
getattr(emp1, 'age') # 返回 'age' 屬性的值
setattr(emp1, 'age', 8) # 添加屬性 'age' 值為 8
delattr(emp1, 'age') # 刪除屬性 'age'
實例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Employee:
'所有員工的基類'
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
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__: 所有員工的基類
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}
__private_attrs:兩個下劃線開頭,聲明該屬性為私有,不能在類的外部被使用或直接訪問.在類內部的方法中使用時 self.__private_attrs.
在類的內部,使用 def 關鍵字可以為類定義一個方法,與一般函數定義不同,類方法必須包含參數 self,且為第一個參數
__private_method:兩個下劃線開頭,聲明該方法為私有方法,不能在類的外部調用.在類的內部調用 self.__private_methods
實例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class JustCounter:
__secretCount = 0 # 私有變量
publicCount = 0 # 公開變量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print self.__secretCount
counter = JustCounter()
counter.count()
counter.count()
print counter.publicCount
print counter.__secretCount # 報錯,實例不能訪問私有變量
Python不允許實例化的類訪問私有數據,但你可以使用 object._className__attrName( 對象名._類名__私有屬性名 )訪問屬性,參考以下實例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Runoob:
__site = "www.runoob.com"
runoob = Runoob()
print runoob._Runoob__site
__foo__: 定義的是特殊方法,一般是系統定義名字 ,類似 __init__() 之類的.
_foo: 以單下劃線開頭的表示的是 protected 類型的變量,即保護類型只能允許其本身與子類進行訪問,不能用於 from module import *
__foo: 雙下劃線的表示的是私有類型(private)的變量, 只能是允許這個類本身進行訪問了.
Python Is an object-oriented p
【python primary 】hasattr Funct