摘要:當引用計數(shù)為零,則不再需要該對象且可以銷毀。這表明當變量被刪除時引用計數(shù)正確的變?yōu)榱恪7椒ㄖ荒茉谘h(huán)被打破后且引用計數(shù)已經(jīng)為零時調(diào)用。這兩步的過程允許引用計數(shù)或垃圾收集刪除已引用的對象,讓弱引用懸空。這允許在方法設(shè)置對象屬性值之前進行處理。
__del__()方法注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python
__del__()方法有一個毫不起眼的用例。
其目的是在對象從內(nèi)存中被移除之前給對象一個機會做一些清理或終結(jié)工作。這個用例通過上下文管理對象和with語句會處理得更清晰。這是第五章《可調(diào)用和上下文的使用》的主要內(nèi)容。創(chuàng)建上下文比用__del__()和Python垃圾收集算法處理起來更可預(yù)知。
如果Python對象有一個相關(guān)的操作系統(tǒng)資源,__del__()方法就是那個最后的機會,干凈利落地從Python應(yīng)用程序中徹底解決資源。例如,Python對象隱藏的一個打開的文件、安裝好的設(shè)備、子進程,或許都能因為資源釋放是__del__()處理的一部分而受益。
__del__()方法并不在任何容易預(yù)知的時刻調(diào)用。對象通過del語句刪除時不會調(diào)用,也不因為名稱空間被移除刪除對象時而調(diào)用。文檔中描述__del__()方法環(huán)境不穩(wěn)定且在異常處理時需額外注意:異常在執(zhí)行時會被忽略,替而代之的是由sys.stderr打印一個警告。
由于這些原因,上下文管理器通常更適合用來實現(xiàn)__del__()。
1、引用計數(shù)和析構(gòu)對于CPython的實現(xiàn),對象有一個引用計數(shù)。當對象賦給一個變量時計數(shù)增加,當變量被移除時減少。當引用計數(shù)為零,則不再需要該對象且可以銷毀。對于簡單的對象,__del__()方法將被調(diào)用且對象將被移除。
對于對象之間循環(huán)引用的復(fù)雜對象,引用計數(shù)可能永遠不會為零且__del__()不能輕易被調(diào)用。
下面這個類,我們可以用一下看看會發(fā)生什么:
class Noisy: def __del__(self): print("Removing {0}".format(id(self)))
我們可以創(chuàng)建對象,如下:
>>> x = Noisy() >>> del x Removing 4313946640
我們創(chuàng)建了并刪除了Noisy對象,我們幾乎立即就看到了來自__del__()方法的反饋。這表明當變量x被刪除時引用計數(shù)正確的變?yōu)榱恪W兞恳坏┫В辉儆?b>Noisy引用的實例,它也可以被清理掉。
下面是一個常見的情況,涉及到經(jīng)常創(chuàng)建的淺拷貝:
>>> ln = [Noisy(), Noisy()] >>> ln2 = ln[:] >>> del ln
這個del語句沒有響應(yīng)。Noisy對象沒有將它們的引用計數(shù)設(shè)為零;因為它們還被引用到其他地方,如下代碼片段所示:
>>> del ln2 Removing 4313920336 Removing 4313920208
ln2變量是ln的淺拷貝列表。Noisy對象被兩個列表引用。直到兩個列表都被刪除,引用計數(shù)減少為零之前它們是不能被銷毀的。
有許多其他方法來創(chuàng)建淺拷貝。以下是創(chuàng)建對象淺拷貝的方法:
a = b = Noisy() c = [Noisy()] * 2
這里的重點是,我們經(jīng)常被對象的引用數(shù)量所迷惑,因為淺拷貝在Python中普遍存在。
2、循環(huán)引用和垃圾收集涉及到循環(huán)是一種常見的情況。一個Parent類,包含一組孩子。每個Child實例包含了一個Parent的引用。
我們將使用這兩個類來看看循環(huán)引用:
class Parent: def __init__(self, *children): self.children = list(children) for child in self.children: child.parent = self def __del__(self): print("Removing {__class__.__name__} {id:d}". format(__class__=self.__class__, id=id(self))) class Child: def __del__(self): print( "Removing {__class__.__name__} {id:d}". format(__class__=self.__class__, id=id(self)))
Parent實例有一組簡單list的孩子。
每個Child實例都有一個Parent類的引用。在初始化期間,孩子們被插入到父母的內(nèi)部集合中,引用被創(chuàng)建。
我們創(chuàng)建的兩個類相當于Noisy,當對象被刪除時我們可以看到如下情形:
>>> p = Parent(Child(), Child()) >>> id(p) 4313921808 >>> del p
Parent和兩個已初始化的Child實例不能被刪除,因為它們相互引用。
我們可以創(chuàng)建一個沒有孩子的父母實例,如下代碼片段所示:
>>> p = Parent() >>> id(p) 4313921744 >>> del p Removing Parent 4313921744
和預(yù)期一樣被刪除。
因為共同的循環(huán)引用,Parent實例及其Child列表實例不能從內(nèi)存中被刪除。如果我們引入垃圾回收接口——gc,我們可以收集和顯示這些不可移除對象。
我們將使用gc.collect()方法來收集所有有__del__()方法的不可移除對象,如下代碼片段所示:
>>> import gc >>> gc.collect() 174 >>> gc.garbage [<__main__.Parent object at 0x101213910>, <__main__.Child object at 0x101213890>, <__main__.Child object at 0x101213650>, <__main__. Parent object at 0x101213850>, <__main__.Child object at 0x1012130d0>, <__main__.Child object at 0x101219a10>, <__main__.Parent object at 0x101213250>, <__main__.Child object at 0x101213090>, <__main__.Child object at 0x101219810>, <__main__.Parent object at 0x101213050>, <__main__.Child object at 0x101213210>, <__main__.Child object at 0x101219f90>, <__main__.Parent object at 0x101213810>, <__main__.Child object at 0x1012137d0>, <__main__.Child object at 0x101213790>]
我們可以看到我們的Parent對象(例如,ID為0x101213910)是其中一個不可移除垃圾。為了減少引用計數(shù)到零,我們既需要更新每個垃圾清單上的Parent實例來移除孩子,又需要更新列表中每個Child實例來刪除Parent實例的引用。
請注意,我們不能通過將代碼放入__del__()方法中來打破這個循環(huán)。__del__()方法只能在循環(huán)被打破后且引用計數(shù)已經(jīng)為零時調(diào)用。當我們有循環(huán)引用,我們可以不再依靠簡單的Python引用計數(shù)來清除內(nèi)存中未使用的對象。我們必須既顯式地打破循環(huán)又使用允許垃圾收集的weakref引用。
3、循環(huán)引用和weakref模塊我們需要循環(huán)引用的情況下但也希望__del__()很好地工作的情況下,我們可以使用弱引用。循環(huán)引用的一個常見用例就是相互引用:父母有一組孩子;每個孩子都有一個引用回到父母。如果一個Player類有多個手,則Hand對象包含一個Player類的引用會很有幫助。
默認的對象引用可以稱為強引用;然而,直接引用是一個更好的術(shù)語。它們被用于Python中的引用計數(shù)機制且如果引用計數(shù)不能刪除對象,也能被垃圾收集器發(fā)現(xiàn)。它們不會被忽略。
強引用一個對象是如此直接。考慮下面的語句:
當我們說:
a = B()
a變量直接引用B類創(chuàng)建的對象。B實例的引用計數(shù)至少為1,因為有一個變量引用了。
弱引用是包含兩個步驟來查找對象之間的聯(lián)系。弱引用將使用x.parent(),調(diào)用弱引用作為一個可調(diào)用對象來跟蹤實際的父母對象。這兩步的過程允許引用計數(shù)或垃圾收集刪除已引用的對象,讓弱引用懸空。
weakref模塊定義一組使用弱引用的集合來代替強引用。這允許我們?nèi)?chuàng)建字典,例如,允許其他未使用對象的垃圾集合。
我們可以修改Parent和Child類來使用弱引用從Child到Parent,允許更簡單的未使用對象的銷毀。
以下是修改后的類,使用弱引用從Child到Parent:
import weakref class Parent2: def __init__(self, *children): self.children = list(children) for child in self.children: child.parent = weakref.ref(self) def __del__(self): print("Removing {__class__.__name__} {id:d}". format(__class__=self.__class__, id=id(self)))
我們已經(jīng)改變了Child到Parent的引用為weakref對象引用。
從Child類中,我們必須通過兩步操作找到Parent對象:
p = self.parent() if p is not None: # process p, the Parent instance else: # the parent instance was garbage collected.
我們可以顯式地檢查確保引用的對象被發(fā)現(xiàn)。很有可能引用被懸空。
當我們使用這個新Parent2類,我們看到引用計數(shù)為0且對象被刪除:
>>> p = Parent2(Child(), Child()) >>> del p Removing Parent2 4303253584 Removing Child 4303256464 Removing Child 4303043344
當weakref引用死了(因為該引用被銷毀),我們有三個潛在的響應(yīng):
重新創(chuàng)建引用。也許會從數(shù)據(jù)庫重新加載它。
在內(nèi)存垃圾收集器意外刪除對象情況下使用warnings模塊編寫調(diào)試信息。
忽略這個問題。
通常,weakref死了是因為對象的引用已被移除:變量超出范圍,名稱空間不再使用,應(yīng)用程序關(guān)閉。出于這個原因,第三個響應(yīng)是相當普遍的。對象試圖創(chuàng)建引用很可能是要被刪除。
4、__del__()和close()方法__del__()最常見的用途是確保文件都已經(jīng)關(guān)閉了。
一般,類定義打開文件將有類似下面顯示的代碼:
__del__ = close
這將確保__del__()方法同樣也是close()方法。
任何比這更復(fù)雜的情況是最好使用上下文管理器。在第五章《使用可調(diào)用和上下文》中可以看到有關(guān)于上下文管理器的更多信息。
__new__()方法和不可變對象__new__()方法的一個用例是用來初始化不可變對象。__new__()方法就是我們構(gòu)建一個未初始化對象的地方。這允許在__init__()方法設(shè)置對象屬性值之前進行處理。
__new__()方法用于擴展不可變類而__init__()方法不能輕易地被覆寫。
以下是行不通的類。我們定義了攜帶單元相關(guān)信息版本的float:
class Float_Fail(float): def __init__(self, value, unit): super().__init__(value) self.unit = unit
我們正在(錯誤地)初始化一個不可變對象。
以下是當我們試圖使用這個類時發(fā)生的情形:
>>> s2 = Float_Fail(6.5, "knots") Traceback (most recent call last): File "", line 1, in TypeError: float() takes at most 1 argument (2 given)
由此我們看到,我們不能輕易地覆寫__init__()方法來建立內(nèi)置不可變的float類。我們與所有其他不可變類一樣有類似的問題。因為不變性定義,我們不能設(shè)置不可變對象、self的屬性值。我們只能在對象構(gòu)造時設(shè)置屬性值。在這之后進入__new__()方法。
__new__()方法是一個很神奇的靜態(tài)方法。這是真的不使用@staticmethod裝飾器。它不使用self變量,它的工作就是創(chuàng)建對象且最終將被分配到self變量。
對于這個用例,方法簽名是__new__(cls, *args, **kwa)。cls參數(shù)是一個類實例必須創(chuàng)建的。對于下一節(jié)中的元類用例,args序列值比這更復(fù)雜。
__new__()的默認實現(xiàn)僅僅做如下操作:return super().__new__(cls)。它委托操作到超類。該工作結(jié)束委托到object.__new__(),構(gòu)建所需類簡單的、空對象。__new__()的參數(shù)和關(guān)鍵字,帶有異常的cls參數(shù),將被傳遞給__init__()作為標準的Python行為的一部分。
有兩個值得注意的例外,這正是我們想要的。以下是一些例外:
當我們想要子類化不可變類定義,稍后我們會深入研究。
當我們需要創(chuàng)建一個元類。這是下一節(jié)的主題,和創(chuàng)建不可變對象完全不同。
相比在創(chuàng)建內(nèi)置不可變類型的子類時覆寫__init__(),我們必須在創(chuàng)建時通過覆寫__new__()來調(diào)整對象。下面是一個示例類定義來展示我們擴展float的正確方法:
class Float_Units(float): def __new__(cls, value, unit): obj = super().__new__(cls, value) obj.unit = unit return obj
在前面的代碼中,我們在創(chuàng)建對象時設(shè)置屬性值。
以下代碼片段給了我們一個附有單位信息的浮點值:
>>> speed = Float_Units(6.5, "knots") >>> speed 6.5 >>> speed * 10 65.0 >>> speed.unit "knots"
注意speed * 10表達式,沒有創(chuàng)建Float_Units對象。這個類定義繼承了來自float的所有操作符特殊方法;float運算特殊方法都能創(chuàng)建float對象。創(chuàng)建Float_Units對象是第七章《創(chuàng)造數(shù)字》的內(nèi)容。
__new__()方法和元類作為元類的一部分,__new__()的其他用例是如何控制構(gòu)建一個類定義。這有別于__new__()如何控制構(gòu)建一個不可變對象,如之前展示的那樣。
元類構(gòu)建類。一旦已經(jīng)形成了一個類對象,類對象就被用于構(gòu)建實例。所有類的元類定義是type。type()函數(shù)被用來創(chuàng)建類對象。
此外,type()函數(shù)可以用來揭示類對象。
下面是一個微不足道的例子用來構(gòu)建一個新的、幾乎沒有直接使用type()類作為構(gòu)造函數(shù):
Useless= type("Useless",(),{})
一旦我們創(chuàng)建這個類,我們可以創(chuàng)建這個Useless類的對象。然而,它們不會做太多因為沒有方法或?qū)傩浴?/p>
我們可以使用這個新創(chuàng)建的Useless類來創(chuàng)建對象。下面是一個例子:
>>> Useless() <__main__.Useless object at 0x101001910> >>> u = _ >>> u.attr = 1 >>> dir(u) ["__class__", "__delattr__", "__dict__", "__dir__", "__doc__", "__eq__", "__format__", "__ge__", "__getattribute__", "__gt__", "__hash__", "__init__", "__le__", "__lt__", "__module__", "__ne__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__weakref__", "attr"]
我們可以將屬性添加到這個類對象。它工作得很好,最起碼可以作為一個對象。
這幾乎相當于使用type.SimpleNamespace或定義了一個類,如下所示:
class Useless: pass
這會帶來嚴重的問題:我們?yōu)槭裁磿谑紫榷x類的定義方式上混亂?
答案是,類的一些默認特性不能完美的適用于一些邊緣情況。我們將討論四個情況來介紹一下元類:
我們可以使用元類來保存一些類的源文本的信息。通過內(nèi)置type構(gòu)建的類使用dict類型來存儲各種方法和類級別屬性。dict本質(zhì)上是無序的,屬性和方法的出現(xiàn)沒有特定的順序。在源處以最初的順序呈現(xiàn)極其不可能的。我們將在第一個例子中展示。
我們將從第4章到7章看到元類用來創(chuàng)建抽象基類(ABC)。依賴元類的__new__()方法來確認具體子類是完整的基礎(chǔ)知識,我們將在第4章《一致設(shè)計的基本知識》介紹。
可以使用元類來簡化某些對象序列化。我們將在第9章《序列化和儲蓄JSON、YAML、Pickle、CSV和XML》看到。
作為最后且相比簡單的例子,我們將看一個類里的自我引用。我們將設(shè)計類引用一個主類。這不是一個父類子類關(guān)系。這是一群同等的子類,但有與一個同等組里面的一個有聯(lián)系且作為的主類。為了與同行保持一致,主類需要引用它本身,不可能沒有元類。這將是我們的第二個例子。
1、元類示例1——已排序?qū)傩?/strong>這是Python語言參考3.3.3節(jié)創(chuàng)建自定義類的典型例子。這個元類將記錄已定義的屬性和方法函數(shù)的順序。
有以下三個部分:
1、創(chuàng)建一個元類。__prepare__()函數(shù)和__new__()函數(shù)的元類將改變構(gòu)建目標類的方式,通過OrderedDict類改變老式的dict類。
2、創(chuàng)建一個基于元類的抽象超類。這個抽象類簡化其他類的繼承。
3、創(chuàng)建抽象超類的子類,得益于元類。
下面是元類示例,將保留創(chuàng)建屬性的順序:
import collections class Ordered_Attributes(type): @classmethod def __prepare__(metacls, name, bases, **kwds): return collections.OrderedDict() def __new__(cls, name, bases, namespace, **kwds): result = super().__new__(cls, name, bases, namespace) result._order = tuple(n for n in namespace if not n.startswith("__")) return result
這個類通過新版本的__prepare__()和__new__()來擴展內(nèi)置的默認元類——type。
__prepare__()方法在創(chuàng)建類之前執(zhí)行,它的工作是創(chuàng)建初始定義的名稱空間對象到被添加的定義中。這個方法可以在其他準備前執(zhí)行類體正在處理。
__new__()靜態(tài)方法在類體元素已經(jīng)被添加到名稱空間后執(zhí)行。給出類對象、類名、超類元組,完整建立好的命名空間映射對象。這是個典型的例子:它委托__new__()的實際工作到超類;元類的超類是內(nèi)置type;我們使用type.__new__()來創(chuàng)建可以調(diào)整的默認類對象。
該示例的__new__()方法添加了一個屬性、_order到類定義中,給我們展示了屬性原來的順序。
我們可以使用這個元類來代替type當定義新的抽象超類,如下所示:
class Order_Preserved(metaclass=Ordered_Attributes): pass
然后我們可以使用這個新的抽象類作為任何新類的超類,如下:
class Something(Order_Preserved): this = "text" def z(self): return False b= "order is preserved" a= "more text"
當我們看到Something類,我們可以看到如下代碼片段:
>>> Something._order >>> ("this", "z", "b", "a")
我們可以考慮利用這些信息來正確的序列化對象或與源定義相關(guān)的提供調(diào)試信息。
2、元類示例2——自引用我們來看一個例子,涉及到單位轉(zhuǎn)換。例如,長度單位包括米、厘米、英寸、英尺和許多其他單位。管理單位轉(zhuǎn)換可以算是一個挑戰(zhàn)。表面上,我們需要一個在所有各種單位中可能的轉(zhuǎn)換因子矩陣。英尺到米、英尺到英寸、英尺到腳碼、米到英寸、米到碼等等——每一個組合。
然而實際上,我們可以做得更好如果我們定義長度的標準單位。我們可以轉(zhuǎn)換任何單位到標準且標準到其他單位。通過這樣做,我們可以很容易的執(zhí)行任何可能的轉(zhuǎn)換為兩步操作,消除了復(fù)雜的所有可能轉(zhuǎn)換的矩陣:英尺到標準、英寸到標準、碼到標準、米到標準。
在接下來的例子中,我們不打算以任何方式子類化float或numbers.Number。比起綁單位到某個值,我們將允許每個值保留一個簡單的數(shù)字。這是Flyweight設(shè)計模式的一個例子。類不定義包含相關(guān)值的對象。對象只包含轉(zhuǎn)換因素。
另一種(綁定單位到值)會導(dǎo)致相當復(fù)雜的多維度分析。雖然有趣,但是它相當?shù)膹?fù)雜。
我們將定義兩個類:Unit和Standard_Unit。我們可以很容易地確定每個Unit類都有一個引用到相對應(yīng)的Standard_Unit。我們?nèi)绾未_保每個Standard_Unit類都有一個引用到自身?類定義里的自引用是不可能的,因為類尚未定義。
以下是我們Unit類定義:
class Unit: """Full name for the unit.""" factor = 1.0 standard = None # Reference to the appropriate StandardUnit name = "" # Abbreviation of the unit"s name. @classmethod def value(class_, value): if value is None: return None return value / class_.factor @classmethod def convert(class_, value): if value is None: return None return value * class_.factor
Unit.value()的意圖是將一個給定單位轉(zhuǎn)換為標準單位值。Unit.convert()方法是將一個標準單位值轉(zhuǎn)換為給定的單位。
單位轉(zhuǎn)換工作,如下面代碼片段所示:
>>> m_f= FOOT.value(4) >>> METER.convert(m_f) 1.2191999999999998
創(chuàng)建的值是內(nèi)置float值。對于溫度,value()和convert()方法需要覆寫,簡單的乘法是行不通的。
對于Standard_Unit,我們可以如下操作:
class INCH: standard= INCH
然而,并沒有什么用。INCH并沒有在INCH類體內(nèi)定義。類在定義前并不存在。
我們可以做這些作為備胎:
class INCH: pass INCH.standard = INCH
然而,這相當讓人討厭。
我們可以定義裝飾器,如下:
@standard class INCH: pass
這個修飾器函數(shù)可以調(diào)整類定義來添加一個屬性。我們將在第八章《修飾符和Mixins——交叉方面》。
因此,我們將定義可以插入循環(huán)引用到類定義的元類,如下:
class UnitMeta(type): def __new__(cls, name, bases, dict): new_class= super().__new__(cls, name, bases, dict) new_class.standard = new_class return new_class
這就迫使將類變量standard加入到類定義。
對于大多數(shù)單位,SomeUnit.standard引用TheStandardUnit類。同時我們也有TheStandardUnit.standard引用TheStandardUnit類。這種Unit和子類Standard_Unit中一致的結(jié)構(gòu)可以幫助編寫文檔和單位轉(zhuǎn)換自動化。
下面是Standard_Unit類:
class Standard_Unit(Unit, metaclass=UnitMeta): pass
單位轉(zhuǎn)換因子1.0繼承自Unit,所以這個類對于提供的值不做任何事情。它包含了特殊的元類定義,這樣它將會有一個自引用來闡明這個類是標準的對于特別尺寸規(guī)格。
作為最優(yōu)選擇,我們可以覆寫value()和convert()方法來避免乘法和除法。
以下是一些單位類定義的示例:
class INCH(Standard_Unit): """Inches""" name = "in" class FOOT(Unit): """Feet""" name = "ft" standard = INCH factor = 1 / 12 class CENTIMETER(Unit): """Centimeters""" name = "cm" standard = INCH factor = 2.54 class METER(Unit): """Meters""" name = "m" standard = INCH factor = .0254
我們定義INCH為標準單位。其他單位的定義將轉(zhuǎn)換到英寸和從英寸轉(zhuǎn)換過來。
我們?yōu)槊總€單位提供了一些文檔:文檔字符串全名和一個短名稱的name屬性。轉(zhuǎn)換因子自動應(yīng)用繼承自Unit的convert()和value()函數(shù)。
在我們的應(yīng)用程序中,這些定義允許以下類型的編程:
>>> x_std= INCH.value(159.625) >>> FOOT.convert(x_std) 13.302083333333332 >>> METER.convert(x_std) 4.054475 >>> METER.factor 0.0254
我們可以給英寸設(shè)置一個特定的尺寸,然后報告該值給任何其他兼容的單位。
元類所做的就是讓我們從單元類定義中做下面這樣的查詢:
>>> INCH.standard.__name__ "INCH" >>> FOOT.standard.__name__ "INCH"
這些類型的引用可以讓我們跟蹤所有給定規(guī)格的各種單位。
總結(jié)我們看了許多基本的特殊方法,這是我們設(shè)計的任何類的基本特征。這些方法已經(jīng)是每個類的一部分,但默認繼承自對象可能不符合我們的處理需求。
我們幾乎總是需要覆寫__repr__()、__str__()和__foramt__()。這些方法的默認實現(xiàn)不是很有幫助。
比較罕見的是如果我們編寫自己的集合需要覆寫__bool__()。這是第六章《創(chuàng)建容器和集合》的主題。
我們經(jīng)常需要覆寫比較關(guān)系和__hash__()方法。定義僅適用于簡單的不可變對象但不適合可變對象。當然我們可能不需要編寫所有的比較運算符;我們將在第八章《修飾符和Mixins——交叉方面》看看@functools.total_ordering裝飾器。
其他兩個基本的特殊方法名稱,__new__()和__del__(),都用于專門的目的。使用__new__()來擴展一個不可變類對它來說是最常見的用例。
這些基本的特殊方法,連同__init__(),將幾乎出現(xiàn)在每一個我們定義的類中。其余的特殊方法都用于專門的目的;它們分為六個類別:
屬性訪問:這些特殊的方法實現(xiàn)我們所看到的object.attribute表達式,object.attribute左邊的賦值和在del語句中的object.attribute。
可調(diào)用:一個特殊的方法實現(xiàn)我們所看到的,函數(shù)作為一個參數(shù)來應(yīng)用,就像內(nèi)置len()函數(shù)一樣。
集合:這些特殊的方法實現(xiàn)眾多集合的特性。包括諸如sequence[index]、mapping[key]和set | set。
數(shù)字:這些特殊方法提供了算術(shù)運算符和比較運算符。我們可以用這些方法來擴展Python使用的數(shù)字領(lǐng)域。
上下文:通過with語句有兩個特殊的方法實現(xiàn)一個上下文管理器。
迭代器:有特殊方法定義迭代器。這不是必要的,作為生成器函數(shù)可以非常優(yōu)雅的處理這個特性。如論如何,我們都要看看如何設(shè)計自己的迭代器。
在下一章,我們將解說屬性、特性和描述符。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/44180.html
摘要:這些基本的特殊方法在類中定義中幾乎總是需要的。和方法對于一個對象,有兩種字符串表示方法。這些都和內(nèi)置函數(shù)以及方法緊密結(jié)合。帶有說明符的合理響應(yīng)是返回。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python 有許多特殊方法允許類與Python緊密結(jié)合,標準庫參考將其稱之為基本,基礎(chǔ)或本質(zhì)可能是更好的術(shù)語。這些特殊...
摘要:比較運算符方法有六個比較運算符。根據(jù)文檔,其映射工作如下第七章創(chuàng)建數(shù)字我們會再次回到比較運算符這塊。同一個類的對象的比較實現(xiàn)我們來看看一個簡單的同一類的比較通過觀察一個更完整的類現(xiàn)在我們已經(jīng)定義了所有六個比較運算符。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __bool__()方法 Python對假有個很...
摘要:有三個用例通過和方法定義相等性檢測和值不可變對象對于有些無狀態(tài)對象,例如這些不能被更新的類型。請注意,我們將為不可變對象定義以上兩個。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __hash__() 方法 內(nèi)置hash()函數(shù)會調(diào)用給定對象的__hash__()方法。這里hash就是將(可能是復(fù)雜的)值縮減...
摘要:第二章與的無縫集成基本特殊方法筆記中有有一些特殊的方法它們允許我們的類和更好的集成和方法通常方法表示的對象對用戶更加友好這個方法是有對象的方法實現(xiàn)的什么時候重寫跟非集合對象一個不包括其他集合對象的簡單對象這類對象格式通常不會特別復(fù) 第二章 與Python的無縫集成----基本特殊方法.(Mastering Objecting-oriented Python 筆記) python中有有一...
閱讀 3493·2021-11-23 10:13
閱讀 863·2021-09-22 16:01
閱讀 909·2021-09-09 09:33
閱讀 630·2021-08-05 09:58
閱讀 1717·2019-08-30 11:14
閱讀 1935·2019-08-30 11:02
閱讀 3265·2019-08-29 16:28
閱讀 1478·2019-08-29 16:09