導航:首頁 > 編程語言 > python魔術繼承

python魔術繼承

發布時間:2022-08-29 01:51:44

python如何實現單例模式

有些時候你的項目中難免需要一些全局唯一的對象,這些對象大多是一些工具性的東西,在Python中實現單例模式並不是什麼難事。以下總結幾種方法:
使用類裝飾器
使用裝飾器實現單例類的時候,類本身並不知道自己是單例的,所以寫代碼的人可以不care這個,只要正常寫自己的類的實現就可以,類的單例有裝飾器保證。
def singleton(cls):
instances = {}
def _wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _wrapper
你會發現singleton裝飾器內部使用了一個dict。當然你也可以用其他的方式,不過以下的實現是錯誤的:
def singleton(cls):
_instance = None #外部作用域的引用對於嵌套的內部作用域是只讀的
def _wrapper(*args, **kwargs):
if _instance is None: #解釋器會拋出"UnboundLocalError: ...referenced before assignment"
_instance = cls(*args, **kwargs) #賦值行為使解釋器將"_instance"看作局部變數
return _instance
return _wrapper
使用元類(__metaclass__)和可調用對象(__call__)
Python的對象系統中一些皆對象,類也不例外,可以稱之為」類型對象」,比較繞,但仔細思考也不難:類本身也是一種對象,只不過這種對象很特殊,它表示某一種類型。是對象,那必然是實例化來的,那麼誰實例化後是這種類型對象呢?也就是元類。
Python中,class關鍵字表示定義一個類對象,此時解釋器會按一定規則尋找__metaclass__,如果找到了,就調用對應的元類實現來實例化該類對象;沒找到,就會調用type元類來實例化該類對象。
__call__是Python的魔術方法,Python的面向對象是」Duck type」的,意味著對象的行為可以通過實現協議來實現,可以看作是一種特殊的介面形式。某個類實現了__call__方法意味著該類的對象是可調用的,可以想像函數調用的樣子。再考慮一下foo=Foo()這種實例化的形式,是不是很像啊。結合元類的概念,可以看出,Foo類是單例的,則在調用Foo()的時候每次都返回了同樣的對象。而Foo作為一個類對象是單例的,意味著它的類(即生成它的元類)是實現了__call__方法的。所以可以如下實現:
class Singleton(type):
def __init__(cls, name, bases, attrs):
super(Singleton, cls).__init__(name, bases, attrs)
cls._instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None
# 以下不要使用'cls._instance = cls(*args, **kwargs)', 防止死循環,
# cls的調用行為已經被當前'__call__'協議攔截了
# 使用super(Singleton, cls).__call__來生成cls的實例
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance

class Foo(object): #單例類
__metaclass__ = Singleton

>>>a = Foo()
>>>b = Foo()
>>>a is b
>>>True
>>>a.x = 1
>>>b.x
>>>1
使用__new__
__init__不是Python對象的構造方法,__init__只負責初始化實例對象,在調用__init__方法之前,會首先調用__new__方法生成對象,可以認為__new__方法充當了構造方法的角色。所以可以在__new__中加以控制,使得某個類只生成唯一對象。具體實現時可以實現一個父類,重載__new__方法,單例類只需要繼承這個父類就好。
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance

class Foo(Singleton): #單例類
a = 1

❷ 魔術方法 python 何時調用

class FileObject:
'''給文件對象進行包裝從而確認在刪除時文件流關閉'''
def __init__(self, filepath='~', filename='sample.txt'):
#讀寫模式打開一個文件
self.file = open(join(filepath, filename), 'r+')
def __del__(self):
self.file.close()
del self.file

❸ python魔術方有哪些

1.__init__
初始化魔術方法
觸發時機:初始化對象時觸發(不是實例化觸發,但是和實例化在一個操作中)
參數:至少有一個self,接收對象
返回值:無
作用:初始化對象的成員
注意:使用該方式初始化的成員都是直接寫入對象當中,類中無法具有

2.__new__
實例化魔術方法
觸發時機: 在實例化對時觸發
參數:至少一個cls 接收當前類
返回值:必須返回一個對象實例
作用:實例化對象
注意:實例化對象是Object類底層實現,其他類繼承了Object的__new__才能夠實現實例化對象。
沒事別碰這個魔術方法,先觸發__new__才會觸發__init__

3.__del__
析構魔術方法
觸發時機:當對象沒有用(沒有任何變數引用)的時候被觸發
參數:一個self 結婚搜對象
返回值:無
作用:使用完對象是回收資源
注意:del不一定會觸發當前方法,只有當前對象沒有任何變數接收時才會觸發

4.__call__
調用對象的魔術方法
觸發時機:將對象當作函數調用時觸發 對象()
參數:至少一個self接收對象,其餘根據調用時參數決定
返回值:根據情況而定
作用:可以將復雜的步驟進行合並操作,減少調用的步驟,方便使用
注意:無

5.__len__
觸發時機:使用len(對象) 的時候觸發
參數:一個參數self
返回值:必須是一個整型
作用:可以設置為檢測對象成員個數,但是也可以進行其他任意操作
注意:返回值必須必須是整數,否則語法報錯,另外該要求是格式要求。

6.__str__
觸發時機:使用print(對象)或者str(對象)的時候觸發
參數:一個self接收對象
返回值:必須是字元串類型
作用:print(對象時)進行操作,得到字元串,通常用於快捷操作
注意:無

7.__repr__
觸發時機:在使用repr(對象)的時候觸發
參數:一個self接收對象
返回值:必須是字元串
作用:將對象轉使用repr化為字元串時使用,也可以用於快捷操作

repr函數和str函數處理字元串只有一個區別:
str的結果 字元串本身 (結果可以被eval執行)
如:x = '無圖言Diao' str() ->無圖言Diao
rerpr的結果 字元串定義結構 (eavl不會執行repr結果)
如:x = '無圖言Diao' repr() ->'無圖言Diao'
備注: 在類中通常情況下__str__和__repr__ 設置相同即可
eval()
函數 將字元串當作python代碼執行
格式:eval(字元串)
返回值:可以有返回值
8.__bool__
觸發時機: 使用bool(對象)的時候觸發
參數:一個self接收對象
返回值:必須是布爾值
作用:根據實際情況決定,可以作為快捷方式使用
注意:僅適合於返回布爾值的操作

9.__format__
觸發時機:使用字元串.format(對象)時候觸發
參數:一個self接收對象,一個參數接收format的{}中的格式,例如:>5
返回值:必須是字元串
作用:設置對象可以作為format的參數,並且自定義對象格式化的規則
注意:無

描述符相關的魔術方法
1.__get__()
觸發時機:在獲取指定描述符操作的成員屬性的值的時候觸發
參數:1描述符對象本身,2描述符描述的屬性所在的對象,描述符描述的對象的類
返回值:必須有,不然無法獲取相應屬性值
注意:僅在描述符中使用

2.__set__()
觸發時機:在設置或者添加指定描述符操作的成員屬性的時候觸發
參數:1描述符對象本身,2描述符描述的屬性所在的對象,3要設置的值
返回值:無
注意:僅在描述符中使用

3.__delete__()
觸發時機:在刪除指定描述符操作的成員屬性的時候觸發
參數:1描述符對象本身,2描述符描述的屬性所在的對象
返回值:無
注意:僅在描述符中使用

與屬性操作相關的魔術方法
1.__getattr__()
觸發時機:獲取不存在的對象成員時觸發
參數:1接收當前對象的self,一個是獲取成員名稱的字元串
返回值:必須有值
作用:為訪問不存在的屬性設置值
注意:getattribute無論何時都會在getattr之前觸發,觸發了getattribute就不會在觸發getattr了

2.__setattr__()
觸發時機:設置對象成員值的時候觸發
參數:1個當前對象的self,一個是要設置的成員名稱字元串,一個是要設置的值
返回值:無 過程操作
作用:接管設置操作,可以在設置前之前進行判斷驗證等行為
注意:在當前方法中無法使用成員=值的方式直接設置成員,否則會無限遞歸,必須藉助object的設置方法來完成

object.__setattr__(參數1,參數2,參數3)

3.__delattr__()
觸發時機:刪除對象成員時觸發
參數:一個當前對象的self
返回值:無
作用:可以在刪除成員時進行驗證。

4.__getattribute__()
觸發時機:使用對象成員時觸發,無論成員是否存在
參數:1個接收當前對象self,一個是獲取的成員的名稱字元串
返回值:必須有
作用:在具有封裝操作(私有化時),為程序開部分訪問許可權使用

5.__dir__()
觸發時機:dir(對象)的時候觸發
參數:1個接收當前對象self
返回值:必須為序列類型(列表,元組,集合等,)
作用:可以自定義成員列表的返回值

運算相關魔術方法(上帝模式)
比較運算相關魔術方法
1.__lt__()
格式:
def __lt__(self,other):
return 數據

特徵:
觸發時機:進行小於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義小於號的行為:x < y 調用 x.lt(y)

2.__le__()
格式:
def __le__(self):
return str

特徵:
觸發時機:進行小於等於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義小於等於號的行為:x <= y 調用 x.le(y)

3.__gt__()
格式:
def __gt__(self):
return str

特徵:
觸發時機:進行大於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義大於號的行為:x > y 調用 x.gt(y)

4.__ge__()
格式:
def __ge__(self):
return str

特徵:
觸發時機:進行大於等於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義大於等於號的行為:x >= y 調用 x.ge(y)

5.__eq__()
格式:
def __eq__(self):
return str

特徵:
觸發時機:進行等於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義大於等於號的行為:x == y 調用 x.eq(y)

6.__ne__()
格式:
def __ne__(self):
return str

特徵:
觸發時機:進行不等於判斷時自動觸發
參數:2個參數第一個是self,第二個判斷的第二個對象
返回值:返回值可以任意類型,推薦布爾值
作用:定義不等號的行為:x != y 調用 x.ne(y)

算術運算相關魔術方法
__add__(self, other) 定義加法的行為:+
__sub__(self, other) 定義減法的行為:-
__mul__(self, other) 定義乘法的行為:
__truediv__(self, other) 定義真除法的行為:/
__floordiv__(self, other) 定義整數除法的行為://
__mod__(self, other) 定義取模演算法的行為:%
__divmod__(self, other) 定義當被 divmod() 調用時的行為
__pow__(self, other[, molo]) 定義當被 power() 調用或 ** 運算時的行為
__lshift__(self, other) 定義按位左移位的行為:<<
__rshift__(self, other) 定義按位右移位的行為:>>
__and__(self, other) 定義按位與操作的行為:&
__xor__(self, other) 定義按位異或操作的行為:^
__or__(self, other) 定義按位或操作的行為:|

反運算相關魔術方法
__radd__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rsub__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rmul__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rtruediv__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rfloordiv__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rmod__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rdivmod__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rpow__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rlshift__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rrshift__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rand__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__rxor__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用
__ror__(self, other) 與上方相同,當左操作數不支持相應的操作時被調用

賦值運算相關魔術方法
__iadd__(self, other) 定義賦值加法的行為:+=
__isub__(self, other) 定義賦值減法的行為:-=
__imul__(self, other) 定義賦值乘法的行為:=
__itruediv__(self, other) 定義賦值真除法的行為:/=
__ifloordiv__(self, other) 定義賦值整數除法的行為://=
__imod__(self, other) 定義賦值取模演算法的行為:%=
__ipow__(self, other[, molo]) 定義賦值冪運算的行為:**=
__ilshift__(self, other) 定義賦值按位左移位的行為:<<=
__irshift__(self, other) 定義賦值按位右移位的行為:>>=
__iand__(self, other) 定義賦值按位與操作的行為:&=
__ixor__(self, other) 定義賦值按位異或操作的行為:^=
__ior__(self, other) 定義賦值按位或操作的行為:|=

一元運算相關魔術方法
__pos__(self) 定義正號的行為:+x
__neg__(self) 定義負號的行為:-x
__abs__(self) 定義當被 abs() 調用時的行為
__invert__(self) 定義按位求反的行為:~x

類型轉換相關魔術方法 JIANG
__complex__(self) 定義當被 complex() 調用時的行為(需要返回恰當的值)
__int__(self) 定義當被 int() 調用時的行為(需要返回恰當的值)
__float__(self) 定義當被 float() 調用時的行為(需要返回恰當的值)
__round__(self[, n]) 定義當被 round() 調用時的行為(需要返回恰當的值)
__index(self)__ 1. 當對象是被應用在切片表達式中時,實現整形強制轉換
2. 如果你定義了一個可能在切片時用到的定製的數值型,你應該定義 index
3. 如果 index 被定義,則 int 也需要被定義,且返回相同的值

上下文管理相關魔術方法
__enter__() 和 __exit__()
enter(self)
1. 定義當使用 with 語句時的初始化行為
2. enter 的返回值被 with 語句的目標或者 as 後的名字綁定

exit(self, exctype, excvalue, traceback)
1. 定義當一個代碼塊被執行或者終止後上下文管理器應該做什麼
2. 一般被用來處理異常,清除工作或者做一些代碼塊執行完畢之後的日常工作

容器類型相關魔術方法
__len__(self) 定義當被 len() 調用時的行為(返回容器中元素的個數)
__getitem__(self, key) 定義獲取容器中指定元素的行為,相當於 self[key]
__setitem__(self, key, value) 定義設置容器中指定元素的行為,相當於 self[key] = value
__delitem__(self, key) 定義刪除容器中指定元素的行為,相當於 del self[key]
__iter__(self) 定義當迭代容器中的元素的行為
__reversed__(self) 定義當被 reversed() 調用時的行為
__contains__(self, item) 定義當使用成員測試運算符(in 或 not in)時的行為

分類: python 面向對象

❹ Python可以多繼承嗎

Python支持多繼承,與C++一樣都會出現一種問題:子類繼承的多個父類又繼承了同一個父類,這時就有可能會出現父類構造方法被調用多次的情況。關於這個問題,我找了一些資料,雖然沒有親自全部驗證,這里我總結一下自己對這個問題的看法。

Python和C++的關於這個問題的解決方案不太一樣,當然Python還要看它的版本。

C++用的方案是引入了虛繼承的語法避免同一個類被構造了多次。

Python用的方法是MRO(method resolution order,方法解析順序) 。在在Python2.3之前,MRO的實現是基於DFS的,而在Python2.3以後MRO的實現是基於C3演算法。找到的資料解釋了一下更換演算法的原因:

為什麼採用C3演算法

C3演算法最早被提出是用於Lisp的,應用在Python中是為了解決原來基於深度優先搜索演算法不滿足本地優先順序,和單調性的問題。

本地優先順序:指聲明時父類的順序,比如C(A,B),如果訪問C類對象屬性時,應該根據聲明順序,優先查找A類,然後再查找B類。

單調性:如果在C的解析順序中,A排在B的前面,那麼在C的所有子類里,也必須滿足這個順序。

------------------------------新式類和舊式類中查找屬性的順序不同-------------------------------------

在新式類中,查找一個要調用的函數或者屬性的時候,是廣度優先搜搜的。

在舊式類當中,是深度優先搜索的。

❺ python 魔術方法什麼意思

魔術方法就跟語法糖差不多

❻ python中什麼是繼承

python繼承:即一個派生類(derived class)繼承基類(base class)的欄位和方法。繼承也允許把一個派生類的對象作為一個基類對象對待。

❼ 如何解決python2不能隱式繼承

繼承是所有開發語言的必修內容,而本文寫的只是Python繼承中的特殊之處,關於繼承概念及內容可以自行網路(不裝B,感覺網路挺好的)1.構造函數:
要說繼承,先要說一下構造函數。Java要求是與類名相同並且無返回值,而Python則是強制要求命名為「__init__()」。
當創建類的對象時,會自動先調用構造函數,一般用於初始化。構造函數可以不寫,那麼程序會隱式自動增加一個空的構造函數。
2.繼承寫法:
(1).class 空格 類名稱 括弧內填寫父類名 冒號具體寫法如下class A:
def __init__(self):
pass
def print_class_name(self):
print "this is class A"
class B(A):
def __init__(self):
pass
if __name__ == "__main__":
class_b = B()
class_b.print_class_name()
上面代碼首先定義了一個名為「A」的類,包含一個名為「print_class_name」的方法。然後,定義一個名為「B」的類,繼承「A」,同時繼承了「A」類的「print_class_name」的方法。
此時「A」類為「B」類的父類或者叫基類,「B」類是「A」類的子類,子類會繼承父類的所有公共方法。
(2).意義:
一字記之曰「懶!」(感嘆號不算字)我始終相信賴人才能推動科學進步。
言歸正傳,假如你要寫一個老王類,包含年齡、性別等方法,後面還要寫一個老王的兒子小王類,也有年齡、性別等方法?
class FatherWang:
def __init__(self, age=43, sex='man'):
self.a = age
self.s = sex
def age(self):
print self.a
def sex(self):
print self.s
class SonWang:
def __init__(self, age=13, sex='man'):
self.a = age
self.s = sex
def age(self):
print self.a
def sex(self):
print self.s
if __name__ == "__main__":
father = FatherWang(43, "man")
father.age()
father.sex()
son = SonWang(13, "man")
son.age()
son.sex()
你會發現兩個類中有相同名稱和功能的方法,這樣寫豈不是很重復很累?(盡管按鍵盤次數不算太多,我依然覺得很累)如果有繼承就很好解決了。
class FatherWang:
def __init__(self, age=43, sex='man'):
self.a = age
self.s = sex
def age(self):
print self.a
def sex(self):
print self.s
class SonWang(FatherWang):
def __init__(self, age=13, sex='man'):
FatherWang.__init(age, sex)
if __name__ == "__main__":
father = FatherWang(43, "man")
father.age()
father.sex()
son = SonWang(13, "man")
son.age()
son.sex()
兩者運行結果完全一樣,但是使用繼承方法卻省了很多按鍵盤的次數。
3.經典類與新式類:
(1)經典類寫法:
class A:
pass
(2)新式類寫法:
class A(object):
pass
可以看出,新式類和經典類的區別在於,是否繼承object這個基類。object是所有類的父類。所以之前不帶「(object)」的寫法,屬於經典類寫法,加上「(object)」就是新式類的寫法。
(3).原因:這里我得吐槽一下Python的版本混亂。2.2版本之前只有經典類寫法,這里有一個問題,代碼如下?
class A:
pass
class B(object):
pass
a = A()
b = B()
print a.__class__
print type(a)
print "----------"
print b.__class__
print type(b)
結果為:
__main__.A
<type 'instance'>
----------
<class '__main__.B'>
<class '__main__.B'>
首先A類為經典類,B類為新式類。__class__屬性和type()方法都是返回對象類型,那麼問題來了,使用經典類的寫法返回結果卻不一致。因此在2.2版本之後出現了新式類來解決這個問題,自然,新式類和經典類還有更大的區別在後面說。另外在3.3版本中,無論使用哪種寫法,python都會隱式的繼承object,所以3.3版本不會再有經典類(在這里我只想問,早干什麼去了!),但是鑒於3.3兼容性問題,貌似沒有太多人用。
4.方法重寫與方法重載
(1).方法重寫:
class FatherWang:
def __init__(self, age=43, sex='man'):
self.a = age
self.s = sex
def age(self):
print self.a
def sex(self):
print self.s
def name(self):
print "Wang_yang"
class SonWang(FatherWang):
def __init__(self, age=13, sex='man'):
FatherWang.__init(age, sex)
def name(self):
print "Wang_xiaoming"
if __name__ == "__main__":
father = FatherWang(43, "man")
father.age()
father.sex()
father.name()
son = SonWang(13, "man")
son.age()
son.sex()
son.name()
比繼承寫法(2)中的代碼相比,兩個類分別多了同名的方法「name」,之前說過子類會繼承父類的方法,那麼這時候兩個類有相同名字的方法,沖突了,怎麼處理?
這個時候,就叫方法重寫。可以理解為,子類的「name」方法把父類的「name」方法覆蓋了,重新寫了,所以調用子類的「name」方法時,會以子類的為准(盡管這種理解並不準確,但是可以很好解釋「方法重寫」這個名詞,後面會講到正確理解)。
注意下面的代碼
class FatherWang:
def __init__(self, age=43, sex="man"):
self.a = age
self.s = sex
print "I am FatherWang"
def age(self):
print "Father age:"+str(self.a)
def sex(self):
print "Father sex:"+str(self.s)
class MotherLi:
def __init__(self, age=40, sex="woman"):
self.a = age
self.s = sex
print "I am MotherLi"
def age(self):
print "Mother age:"+str(self.a)
def sex(self):
print "Mother sex"+str(self.s)
class SonWang(FatherWang, MotherLi):
def __init__(self, age=13, sex="man"):
FatherWang.__init__(self, age, sex)
MotherLi.__init__(self, age, sex)
print "I am SonWang"
if __name__ == "__main__":
son = SonWang()
son.age()
son.sex()
執行結果:
I am FatherWang
I am MotherLi
I am SonWang
Father age:13
Father sex:man
在之前代碼上稍作修改,另外增加了一個MotherLi的類,SonWang類繼承了FatherWang類和MotherLi類。注意,這是經典類的寫法。
首先,我們知道了python多繼承的寫法,就是在括弧中上一個父類後面加個逗號,然後再寫上下一個父類的名字:
class SonWang(FatherWang, MotherLi):
其次,FatherWang類和MotherLi類,都有名為age和sex方法,SonWang類為什麼會繼承FatherWang類的方法呢?那麼把SonWang類的繼承順序改一下class SonWang(MotherLi, FatherWang):
就會發現繼承的是MotherLi類的方法。
通過結果可知,是按照繼承的順序。
讓我們把代碼結構變得更發雜一些吧,我想會崩潰的,哈哈哈?
class Grandfather:
def __init__(self, age=73, sex="man"):
self.a = age
self.s = sex
print "I am Grandfather"
def age(self):
print "Grandfather age:"+str(self.a)
def sex(self):
print "Grandfather sex:"+str(self.s)
def Interesting(self):
print "Grandfather Interesting"
class Grandmother:
def __init__(self, age=70, sex="woman"):
self.a = age
self.s = sex
print "I am Grandmother"
def age(self):
print "Grandmother age:"+str(self.a)
def sex(self):
print "Grandmother sex:"+str(self.s)
def Interesting(self):
print "Grandmother Interesting"
class FatherWang(Grandfather, Grandmother):
def __init__(self, age=43, sex="man"):
self.a = age
self.s = sex
Grandfather.__init__(self, age, sex)
Grandmother.__init__(self, age, sex)
print "I am FatherWang"
def age(self):
print "Father age:"+str(self.a)
def sex(self):
print "Father sex:"+str(self.s)
class MotherLi(Grandfather, Grandmother):
def __init__(self, age=40, sex="woman"):
self.a = age
self.s = sex
Grandfather.__init__(self, age, sex)
Grandmother.__init__(self, age, sex)
print "I am MotherLi"
def age(self):
print "Mother age:"+str(self.a)
def sex(self):
print "Mother sex"+str(self.s)
def Interesting(self):
print "MotherLi Interesting"
class SonWang(FatherWang, MotherLi):
def __init__(self, age=13, sex="man"):
FatherWang.__init__(self, age, sex)
MotherLi.__init__(self, age, sex)
print "I am SonWang"
if __name__ == "__main__":
son = SonWang()
son.age()
son.sex()
son.Interesting()
執行結果:
I am Grandfather
I am Grandmother
I am FatherWang
I am Grandfather
I am Grandmother
I am MotherLi
I am SonWang
Father age:13
Father sex:man
Grandfather Interesting
話說,我自己都有點兒暈。簡單來講,就是兒子繼承了老爸、老媽,然後老爸繼承了爺爺、奶奶,媽媽繼承了老爺、姥姥。(真是一大家子啊)通過執行結果可知,兒子類先找到老爸類,然後再找老爸類的第1個父類爺爺類,此時發現爺爺類沒有父類了,那麼執行初始化。然後還要繼續找到老爸類的第2個父類奶奶類,此時發現奶奶類沒有父類了,執行初始化。此時老爸類的所有父類都初始化完成,初始化自己。然後開始找媽媽類……那麼為什麼Interesting方法會使用爺爺類的呢?奶奶類、老爺類、姥姥類都有啊?首先兒子類沒有Interesting方法,會先找第1個父類老爸類。發現老爸類也沒有,再找老爸類的第1個父類,發現找到了,那麼就直接調用不再往下找了。
結論:經典類的多繼承,按照繼承順序查找。即,從左到右,從下到上的方式。注意,只有經典類是這樣的!
(2).新式類的多繼承:
class Grandfather(object):
def __init__(self, age=73, sex="man"):
self.a = age
self.s = sex
print "I am Grandfather"
def age(self):
print "Grandfather age:"+str(self.a)
def sex(self):
print "Grandfather sex:"+str(self.s)
def Interesting(self):
print "Grandfather Interesting"
class Grandmother(object):
def __init__(self, age=70, sex="woman"):
self.a = age
self.s = sex
print "I am Grandmother"
def age(self):
print "Grandmother age:"+str(self.a)
def sex(self):
print "Grandmother sex:"+str(self.s)
def Interesting(self):
print "Grandmother Interesting"
class FatherWang(Grandfather, Grandmother):
def __init__(self, age=43, sex="man"):
self.a = age
self.s = sex
Grandfather.__init__(self, age, sex)
Grandmother.__init__(self, age, sex)
print "I am FatherWang"
def age(self):
print "Father age:"+str(self.a)
def sex(self):
print "Father sex:"+str(self.s)
class MotherLi(Grandfather, Grandmother):
def __init__(self, age=40, sex="woman"):
self.a = age
self.s = sex
Grandfather.__init__(self, age, sex)
Grandmother.__init__(self, age, sex)
print "I am MotherLi"
def age(self):
print "Mother age:"+str(self.a)
def sex(self):
print "Mother sex"+str(self.s)
def Interesting(self):
print "MotherLi Interesting"
class SonWang(FatherWang, MotherLi):
def __init__(self, age=13, sex="man"):
FatherWang.__init__(self, age, sex)
MotherLi.__init__(self, age, sex)
print "I am SonWang"
if __name__ == "__main__":
son = SonWang()
son.age()
son.sex()
son.Interesting()
執行結果:
I am Grandfather
I am Grandmother
I am FatherWang
I am Grandfather
I am Grandmother
I am MotherLi
I am SonWang
Father age:13
Father sex:man
MotherLi Interesting

閱讀全文

與python魔術繼承相關的資料

熱點內容
去哪裡找按摩師很漂亮的app 瀏覽:818
86x99用簡便演算法計算 瀏覽:829
php截圖flash 瀏覽:272
卸載聯想app哪個好 瀏覽:719
php文字轉圖片 瀏覽:329
豆客後台怎麼加密碼 瀏覽:574
jpg轉換pdf破解版 瀏覽:978
php基礎書籍推薦 瀏覽:777
伺服器與外網不通如何驗證 瀏覽:351
電子版是不是就是文件夾 瀏覽:50
游戲屬性文件加密 瀏覽:462
如何讓安卓手機桌面圖標下移 瀏覽:529
ubuntuphp5環境搭建 瀏覽:100
賭癮解壓視頻 瀏覽:917
晉城移動dns伺服器地址 瀏覽:296
php開源文庫系統 瀏覽:136
android記事本源碼 瀏覽:407
安卓11小游戲怎麼玩法 瀏覽:190
gif有損壓縮 瀏覽:937
windows下安裝linux命令操作 瀏覽:844