Ⅰ 學明白了 python 多繼承中的 MRO 演算法有什麼用

可能你有C++的基礎吧,C++確實可以不用帶上this。
我把你的代碼稍微改了一下,你可以分別看看版cls1.n、cls2.n、self.n的輸出權。
class cls1:
n=3
class cls2(cls1):
def __init__(self,cls1=cls1):
cls2.n += 1
self.n += 2
print 'cls1.n:%s'%cls1.n
print 'cls2.n:%s'%cls2.n
print 'self.n:%s'%self.n

cls2()
print 'cls1.n:%s'%cls1.n
可以看出兩個類和一個對象都可以在這里調用它們的n屬性,如果只敲一個n別人讀你的代碼時就比較容易產生岐義,雖然少打了5個字元,但是不符合簡單明確的pythonic哲學。
當然你也可以就認為python語法規則就是這么規定的。

Ⅱ 是否有等同於局部類任何Python

1. 如果你的問題真的只是正與一大班在編輯器中,第一個解決方案,我會真正期待的是一個更好的方式來打破的問題。第二個解決方案是一個更好的編輯器,最好是有代碼折疊。
這就是說,有幾個方法你可能會打破一個班級分成多個文件。python讓一個文件夾作為一個模塊通過將一個__init__.py在裡面,然後可以從其他文件中導入的東西。我們'這種能力在每一個解決方案。做一個調用,比如文件夾,bigclass第一。
在文件夾放.py文件將你的類.each人都應該包含在最終的類,而不是類函數和變數定義。在__init__.py在文件夾中寫入以下加入他們一起。
class Bigclass(object):

from classdef1 import foo, bar, baz, quux
from classdef2 import thing1, thing2
from classdef3 import magic, moremagic
# unfortunately, "from classdefn import *" is an error or warning

num = 42 # add more members here if you like

這有你最終直接來源於單個類的優勢object,這將很好看在你的繼承圖。
你的類的你多重繼承的部分。在你的各個模塊,你會寫一個類定義Bigclass帶之類的部件。然後在你的__init__.py寫:
import classdef1, classdef2, classdef3

class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
num = 42 # add more members if desired

如果多重繼承的問題,你可以使用單繼承:只需每個類繼承自另外一個連鎖的方式。假設你沒有在多個類中定義的話,就是順序無關緊要。例如,classdef2.py會是這樣的:
import classdef1
class Bigclass(classdef1.Bigclass):
# more member defs here

classdef3將進口Bigclass從classdef2並添加到它,等等。您的__init__.py將剛剛導入的最後一個:
from classdef42 import Bigclass

我一般喜歡#1它是更加明確要導入從哪個文件,但所有這些解決方案可以為你工作。
類中的任何一種情況你可以導入,使用文件夾作為模塊from bigclass import Bigclass

2.
包含數百行確實發生「在野外」(我看到在類定義中流行的開放源代碼的基於Python的,但我相信,如果你思考什麼都做,將有可能減少到可管理的大多數類的長度。點的例子:
尋找其中大部分代碼出現一次以上的地方。打破代碼分解到其與調用它的每一個地方
「私人」的方法是做任何對象狀態的可以帶出的類作為獨立的功能。
只應在特定條件下被調用的方法可能表明需要在子類的地方。
直接解決你的問題,它可以分裂一個類的定義.a種方法是「猴子補丁」之類通過定義它,然後添加外功能,它另一個是內置的type功能「手動」來創建類,其提供的任何基類,並在一本字典屬性。但我不這樣做,只是定義將是長期的,否則。那種治癒的是比疾病在我看來更糟。

3.
我已經有類似玩弄各地。是一個抽象語法樹節點的類層次結構,然後我希望把所有的如:以漂亮的funtions在一個單獨的prettyprint.py文件,但仍然有他們的班。
有一件事我想是一個裝飾的放裝飾的功能作為一個屬性上指定的類。在我而言這是prettyprint.py包含大量的def prettyprint(self)所有裝飾著不同@inclass(...)有這方面的一個問題是,必須確保該子文件總是進口的,而且它們所依賴的主類,這對於一個循環依賴,這可能
def inclass(kls):
"""
Decorator that adds the decorated function
as a method in specified class
"""
def _(func):
setattr(kls,func.__name__, func)
return func
return _

## exampe usage
class C:
def __init__(self, d):
self.d = d

# this would be in a separate file.
@inclass(C)
def meth(self, a):
"""Some method"""
print "attribute: %s - argument: %s" % (self.d, a)

i = C(10)
print i.meth.__doc__
i.meth(20)

4.
我已經,但是,這個包稱為部分索賠增加的部分類別的支持。
好像還有一些其他的方法,你會這樣自己也是如此。
你可以分開的類的部分作為單獨的文件混入,然後將它們導入所有和繼承他們。
或者,您也可以在每個類的,然後在中央文件中導入,並指定其為一個類的屬性,來創建整個對象。像這樣:
a.py:
def AFunc( self, something ):
# Do something
pass

b.py:
def BFunc( self, something ):
# Do something else
pass

c.py:
import a, b

class C:
AFunc = a.AFunc
BFunc = b.BFunc

你甚至可以走那麼遠,自動完成這個過程,如果你真的想要的-通過所有模塊所提供的功能迴路a和b然後將它們添加為屬性上C。雖然這可能是總矯枉過正。
可能還有其他的(可能更好)的方式去了解它,但那些都是閃入腦海的2。

5.
首先,我想說,這可能不是一個好主意只是為了找到你的類中的地方更容易-這將是最好的補充高亮部分等。不過,我看你能做到這一點有兩種方式:
寫的類在幾個文件,然後讀取它們的文字,將它們連接起來,並exec結果字元串。
在每個文件創建一個單獨的類,然後繼承他們都為一個大師班的混入。但是,如果你繼承另一個類已經就可能導致MRO問題。你能解決這個問題通過創建其手動解決MRO你的大師班,但是這可能
最簡單的是第一個選項。

6.
首先,我不明白怎麼分裂全班分成多個文件,使編輯變得更容易.a個體面的IDE應該能夠很容易地找到是否在一個文件或多個,如果你是一個體面的IDE,分裂的維護者有猜測哪些文件是,這聽起來更難,而不是更容易。
更多這個類-如此之大,你想有一個特殊的語言功能只是為了支撐其重量-破碎的聲音。我們是如何多行代碼在談論什麼?幾乎可以肯定,這將是一個更好的主意,這樣做的一個:
重構代碼復制到更少的,更普遍的原語
定義一個基類和子類與擴展它作為卡羅利霍瓦特在暗示(這是最接近於「局部類」那你問我會贊同)
定義一些單獨的類來封裝這種不同部分
類的功能,這個類的實例的
較小的。

7.
的情況-我想slipt我班2個文件。
原因是-我想第1部分為GUI布局,只有布局
而另一個文件保存了所有的功能。
像C#的部分類.a個用於XAML和另一個用於功能。

8.
你可以做到這一點的,像這樣的裝飾:
class Car(object):

def start(self):
print 'Car has started'

def extends(klass):
def decorator(func):
setattr(klass, func.__name__, func)
return func
return decorator

#this can go in a different mole/file
@extends(Car)
def do_start(self):
self.start()

#so can this
car = Car()
car.do_start()

#=> Car has started

Ⅲ Python,super繼承的問題,求解答。

這可能需要了解下 python 當中的:
Method Resolution Order (mro)
中文的話,應該是"方法解析順序".我也是剛查的.
如果你在最後輸出 D().__class__.__mro__
你就可以看到 python 是按什麼樣的順序處理繼承的了.
它給我的輸出是:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
先 D_start - B_start - C_start - A_start - A_end - C_end - B_end - D_end

Ⅳ python類中的super,原理如何MRO是什麼東東

首先得說明的是,Python的類分為經典類 和 新式類
經典類是python2.2之前的東西,但是在2.7還在兼容,但是在3之後的版本就只承認新式類了
新式類在python2.2之後的版本中都可以使用!

Ⅳ python如何進階學習

Python進階學習,比較高端的是Python架構師,想要成為Python架構師,不僅要技術過硬,回還要有全局意識,擁有豐富的項答目經驗,這些可以從實踐中來,也可以向資深架構師學習,目前,也有培訓機構培訓這項技能,這些都是很好的學習途徑!

Ⅵ python中super為什麼能解決多重繼承問題

1. super 並不是一個函數,是一個類名,形如 super(B, self) 事實上調用了 super 類的初始化函數,產生了一個 super 對象;

2. super 類的初始化函數並沒有做什麼特殊的操作,只是簡單記錄了類類型和具體實例;
3. super(B, self).func 的調用並不是用於調用當前類的父類的 func 函數;
4. Python 的多繼承類是通過 mro 的方式來保證各個父類的函數被逐一調用,而且保證每個父類函數只調用一次(如果每個類都使用 super);

5. 混用 super 類和非綁定的函數是一個危險行為,這可能導致應該調用的父類函數沒有調用或者一個父類函數被調用多次。
6. 用 super,遇到修改父類的名字時等情況

Ⅶ Python有什麼缺點呢

Python的定位是「優雅」、「明確」、「簡單」,所以Python程序看上去總是簡單易懂,初學者學Python,不但入門容易,而且將來深入下去,可以編寫那些非常非常復雜的程序。
python語言的優點
⑴作為初學python的科班出身的小白,python非常簡單,非常適合人類閱讀。閱讀一個良好的Python程序就感覺像是在讀英語一樣,盡管這個英語的要求非常嚴格!Python的這種偽代碼本質是它最大的優點之一。它使你能夠專注於解決問題而不是去搞明白語言本身。
⑵易學。python雖然是用c語言寫的,但是它擯棄了c中非常復雜的指針,簡化了python的語法。
⑶Python是FLOSS(自由/開放源碼軟體)之一。簡單地說,你可以自由地發布這個軟體的拷貝、閱讀它的源代碼、對它做改動、把它的一部分用於新的自由軟體中。Python希望看到一個更加優秀的人創造並經常改進。
⑷可移植性————由於它的開源本質,Python已經被移植在許多平台上(經過改動使它能夠工作在不同平台上)。如果你小心地避免使用依賴於系統的特性,那麼你的所有Python程序無需修改就可以在下述任何平台上面運行。這些平台包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至還有PocketPC、Symbian以及Google基於linux開發的Android平台!
⑸在計算機內部,Python解釋器把源代碼轉換成稱為位元組碼的中間形式,然後再把它翻譯成計算機使用的機器語言並運行。事實上,由於你不再需要擔心如何編譯程序,如何確保連接轉載正確的庫等等,所有這一切使得使用Python更加簡單。由於你只需要把你的Python程序拷貝到另外一台計算機上,它就可以工作了,這也使得你的Python程序更加易於移植。
⑹Python既支持面向過程的函數編程也支持面向對象的抽象編程。在面向過程的語言中,程序是由過程或僅僅是可重用代碼的函數構建起來的。在面向對象的語言中,程序是由數據和功能組合而成的對象構建起來的。與其他主要的語言如C++和Java相比,Python以一種非常強大又簡單的方式實現面向對象編程。
⑺ 可擴展性和可嵌入性。如果你需要你的一段關鍵代碼運行得更快或者希望某些演算法不公開,你可以把你的部分程序用C或C++編寫,然後在你的Python程序中使用它們。你可以把Python嵌入你的C/C++程序,從而向你的程序用戶提供腳本功能。
⑻豐富的庫。Python標准庫確實很龐大。python有可定義的第三方庫可以使用。它可以幫助你處理各種工作,包括正則表達式、文檔生成、單元測試、線程、資料庫、網頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、HTML、WAV文件、密碼系統、GUI(圖形用戶界面)、Tk和其他與系統有關的操作。記住,只要安裝了Python,所有這些功能都是可用的。這被稱作Python的「功能齊全」理念。除了標准庫以外,還有許多其他高質量的庫,如wxPython、Twisted和Python圖像庫等等。
⑼ Python確實是一種十分精彩又強大的語言。它合理地結合了高性能與使得編寫程序簡單有趣的特色。
⑽規范的代碼。Python採用強制縮進的方式使得代碼具有極佳的可讀性。
python語言的缺點
很多時候不能將程序連寫成一行,如import sys;for i in sys.path:print i。而perl和awk就無此限制,可以較為方便的在shell下完成簡單程序,不需要如Python一樣,必須將程序寫入一個.py文件。(對很多用戶而言這也不算是限制)
⑴運行速度,有速度要求的話,用C++改寫關鍵部分吧。不過對於用戶而言,機器上運行速度是可以忽略的。因為用戶根本感覺不出來這種速度的差異。
⑵既是優點也是缺點,python的開源性使得Python語言不能加密,但是目前國內市場純粹靠編寫軟體賣給客戶的越來越少,網站和移動應用不需要給客戶源代碼,所以這個問題就是問題。不過隨著時間的推移,很多國內軟體公司,尤其是游戲公司,也開始規模使用他。
⑶ 構架選擇太多(沒有像C#這樣的官方.net構架,也沒有像ruby由於歷史較短,構架開發的相對集中。Ruby on Rails 構架開發中小型web程序天下無敵)。不過這也從另一個側面說明,python比較優秀,吸引的人才多,項目也多。

Ⅷ 又來求助了,大神求解答 python類繼承的問題

老式類就是經典類,不是繼承自object類.在多繼承時採用深度優先遍歷父類.
新式類就是基類繼承自object類 class xxx(object).多繼承時採用一種新的C3 演算法來遍歷父類.
實例如下:

新式類的列印結果如下:

1speak: I am mother

舊式類的列印結果如下:

1speak: I am GrandFather

由此我們可以看出新式類的搜索過程為:Son-->Father-->Mother,而舊式類的搜索過程為:Son-->Father-->GrandFather

我們可以看出舊式類和我們預期的繼承不太一樣。

老式類就是經典類,不是繼承自object類.在多繼承時採用深度優先遍歷父類.
新式類就是基類繼承自object類 class xxx(object).多繼承時採用一種新的C3 演算法來遍歷父類.

為什麼採用C3演算法呢?

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

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

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

為了解釋C3演算法,我們引入了mro(mro即 method resolution order (方法解釋順序),主要用於在多繼承時判斷屬性的路徑(來自於哪個類))。

我們可以通過class.mro()來查看python類的mro

C3演算法
判斷mro要先確定一個線性序列,然後查找路徑由由序列中類的順序決定。所以C3演算法就是生成一個線性序列。
如果繼承至一個基類:
class B(A)
這時B的mro序列為[B,A]

如果繼承至多個基類
class B(A1,A2,A3 ...)
這時B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])


merge操作就是C3演算法的核心。
遍歷執行merge操作的序列,如果一個序列的第一個元素,是其他序列中的第一個元素,或不在其他序列出現,則從所有執行merge操作序列中刪除這個元素,合並到當前的mro中。
merge操作後的序列,繼續執行merge操作,直到merge操作的序列為空。
如果merge操作的序列無法為空,則說明不合法。

例子:
class A(O):pass
class B(O):pass
class C(O):pass
class E(A,B):pass
class F(B,C):pass
class G(E,F):pass

A、B、C都繼承至一個基類,所以mro序列依次為[A,O]、[B,O]、[C,O]
mro(E) = [E] + merge(mro(A), mro(B), [A,B])
= [E] + merge([A,O], [B,O], [A,B])
執行merge操作的序列為[A,O]、[B,O]、[A,B]
A是序列[A,O]中的第一個元素,在序列[B,O]中不出現,在序列[A,B]中也是第一個元素,所以從執行merge操作的序列([A,O]、[B,O]、[A,B])中刪除A,合並到當前mro,[E]中。
mro(E) = [E,A] + merge([O], [B,O], [B])
再執行merge操作,O是序列[O]中的第一個元素,但O在序列[B,O]中出現並且不是其中第一個元素。繼續查看[B,O]的第一個元素B,B滿足條件,所以從執行merge操作的序列中刪除B,合並到[E, A]中。
mro(E) = [E,A,B] + merge([O], [O])
= [E,A,B,O]

Ⅸ 如何理解 Python 的 Descriptor

一般來說,一個描述器是一個有「綁定行為」的對象屬性(object attribute),它的訪問控制被描述器協議方法重寫。這些方法是 __get__(), __set__(), 和 __delete__() 。有這些方法的對象叫做描述器。
默認對屬性的訪問控制是從對象的字典裡面(__dict__)中獲取(get), 設置(set)和刪除(delete)它。舉例來說, a.x 的查找順序是, a.__dict__['x'] , 然後 type(a).__dict__['x'] , 然後找 type(a) 的父類(不包括元類(metaclass)).如果查找到的值是一個描述器, Python就會調用描述器的方法來重寫默認的控制行為。這個重寫發生在這個查找環節的哪裡取決於定義了哪個描述器方法。注意, 只有在新式類中時描述器才會起作用。(新式類是繼承自 type 或者 object 的類)
描述器是強大的,應用廣泛的。描述器正是屬性, 實例方法, 靜態方法, 類方法和 super 的背後的實現機制。描述器在Python自身中廣泛使用,以實現Python 2.2中引入的新式類。描述器簡化了底層的C代碼,並為Python的日常編程提供了一套靈活的新工具。
描述器協議

descr.__get__(self, obj, type=None) --> value
descr.__get__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

一個對象如果是一個描述器,被當做對象屬性(很重要)時重寫默認的查找行為。
如果一個對象同時定義了__get__和__set__,它叫data descriptor。僅定義了__get__的描述器叫non-data descriptor。
data descriptor和non-data descriptor區別在於: 相對於實例的字典的優先順序,如果實例字典有與描述器具同名的屬性,如果描述器是data descriptor,優先使用data descriptor。如果是non-data descriptor,優先使用字典中的屬性。

class B(object):

def __init__(self):
self.name = 'mink'

def __get__(self, obj, objtype=None):
return self.name

class A(object):
name = B()

a = A()
print a.__dict__ # print {}
print a.name # print mink
a.name = 'kk'
print a.__dict__ # print {'name': 'kk'}
print a.name # print kk

這里B是一個non-data descriptor所以當a.name = 'kk'的時候,a.__dict__里會有name屬性, 接下來給它設置__set__

def __set__(self, obj, value):
self.name = value

... do something

a = A()
print a.__dict__ # print {}
print a.name # print mink
a.name = 'kk'
print a.__dict__ # print {}
print a.name # print kk

因為data descriptor訪問屬性優先順序比實例的字典高,所以a.__dict__是空的。
描述器的調用
描述器可以直接這么調用: d.__get__(obj)
然而更常見的情況是描述器在屬性訪問時被自動調用。舉例來說, obj.d 會在 obj 的字典中找 d ,如果 d 定義了 __get__ 方法,那麼 d.__get__(obj) 會依據下面的優先規則被調用。
調用的細節取決於 obj 是一個類還是一個實例。另外,描述器只對於新式對象和新式類才起作用。繼承於 object 的類叫做新式類。
對於對象來講,方法 object.__getattribute__() 把 b.x 變成 type(b).__dict__['x'].__get__(b, type(b)) 。具體實現是依據這樣的優先順序:資料描述器優先於實例變數,實例變數優先於非資料描述器,__getattr__()方法(如果對象中包含的話)具有最低的優先順序。完整的C語言實現可以在 Objects/object.c 中 PyObject_GenericGetAttr() 查看。
對於類來講,方法 type.__getattribute__() 把 B.x 變成 B.__dict__['x'].__get__(None, B) 。用Python來描述就是:

def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v

其中重要的幾點:
描述器的調用是因為 __getattribute__()
重寫 __getattribute__() 方法會阻止正常的描述器調用
__getattribute__() 只對新式類的實例可用
object.__getattribute__() 和 type.__getattribute__() 對 __get__() 的調用不一樣
資料描述器總是比實例字典優先。
非資料描述器可能被實例字典重寫。(非資料描述器不如實例字典優先)
super() 返回的對象同樣有一個定製的 __getattribute__() 方法用來調用描述器。調用 super(B, obj).m() 時會先在 obj.__class__.__mro__ 中查找與B緊鄰的基類A,然後返回 A.__dict__['m'].__get__(obj, A) 。如果不是描述器,原樣返回 m 。如果實例字典中找不到 m ,會回溯繼續調用 object.__getattribute__() 查找。(譯者註:即在 __mro__ 中的下一個基類中查找)
注意:在Python 2.2中,如果 m 是一個描述器, super(B, obj).m() 只會調用方法 __get__() 。在Python 2.3中,非資料描述器(除非是個舊式類)也會被調用。 super_getattro() 的實現細節在: Objects/typeobject.c ,[del] 一個等價的Python實現在 Guido's Tutorial [/del] (譯者註:原文此句已刪除,保留供大家參考)。
以上展示了描述器的機理是在 object, type, 和 super 的 __getattribute__() 方法中實現的。由 object 派生出的類自動的繼承這個機理,或者它們有個有類似機理的元類。同樣,可以重寫類的 __getattribute__() 方法來關閉這個類的描述器行為。
描述器例子
下面的代碼中定義了一個資料描述器,每次 get 和 set 都會列印一條消息。重寫 __getattribute__() 是另一個可以使所有屬性擁有這個行為的方法。但是,描述器在監視特定屬性的時候是很有用的。

class RevealAccess(object):
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""

def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name

def __get__(self, obj, objtype):
print 'Retrieving', self.name
return self.val

def __set__(self, obj, val):
print 'Updating' , self.name
self.val = val

>>> class MyClass(object):
x = RevealAccess(10, 'var "x"')
y = 5

>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> m.x
Retrieving var "x"
20
>>> m.y
5

這個協議非常簡單,並且提供了令人激動的可能。一些用途實在是太普遍以致於它們被打包成獨立的函數。像屬性(property), 方法(bound和unbound method), 靜態方法和類方法都是基於描述器協議的。