国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[譯] 與 Python 無縫集成——基本特殊方法 1

yzd / 3422人閱讀

摘要:這些基本的特殊方法在類中定義中幾乎總是需要的。和方法對(duì)于一個(gè)對(duì)象,有兩種字符串表示方法。這些都和內(nèi)置函數(shù)以及方法緊密結(jié)合。帶有說明符的合理響應(yīng)是返回。

  

注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python

有許多特殊方法允許類與Python緊密結(jié)合,標(biāo)準(zhǔn)庫(kù)參考將其稱之為基本,基礎(chǔ)或本質(zhì)可能是更好的術(shù)語(yǔ)。這些特殊方法構(gòu)成了創(chuàng)建與其他Python特性無縫集成的類的基礎(chǔ)。

例如,對(duì)于給定對(duì)象的值,我們需要字符串表示。基類、對(duì)象都有默認(rèn)的__repr__()__str__()用于提供對(duì)象的字符串表示。遺憾的是,這些默認(rèn)表示不提供信息。我們總是想要覆蓋這些默認(rèn)定義中的一個(gè)或兩個(gè)。我們可以看看__format__(),這個(gè)更復(fù)雜但目的和前面是一樣的。

我們也可以看看其他轉(zhuǎn)換,特別是__hash__()__bool__()、和__bytes__()。這些方法將一個(gè)對(duì)象轉(zhuǎn)換成數(shù)字、true/false值或字符串的字節(jié)。例如,當(dāng)我們實(shí)現(xiàn)__bool__()時(shí),可以在if語(yǔ)句中使用對(duì)象,如下:if someobject:

然后,我們可以看看實(shí)現(xiàn)比較操作符的特殊方法__lt__()__le__()__eq__()__ne__()__gt__()__ge__()

這些基本的特殊方法在類中定義中幾乎總是需要的。

最后我們來看看__new__()__del__(),因?yàn)檫@些方法的用例相當(dāng)復(fù)雜。每當(dāng)我們需要其他基本特殊方法時(shí),是不需要這些的。

我們會(huì)詳細(xì)看看如何添加這些特殊方法來擴(kuò)大一個(gè)簡(jiǎn)單的類定義。我們需要看一下兩個(gè)從對(duì)象繼承的默認(rèn)行為,這樣我們可以了解需要什么樣的覆蓋以及何時(shí)真正需要。

__repr__()__str__() 方法

對(duì)于一個(gè)對(duì)象,Python有兩種字符串表示方法。這些都和內(nèi)置函數(shù)__repr__()__str__()__print__()以及string.format()方法緊密結(jié)合。

str()方法表示的對(duì)象通常是適用于人理解的,由對(duì)象的__str__()方法創(chuàng)建。

repr()方法表示的對(duì)象通常是適用于解釋器理解的,可能是完整的Python表達(dá)式來重建對(duì)象。文檔中是這樣說的:對(duì)于許多類型,這個(gè)函數(shù)試圖返回一個(gè)字符串,將該字符串傳遞給eval()會(huì)重新生成對(duì)象。
這是由對(duì)象的__repr__()方法創(chuàng)建的。

print()函數(shù)會(huì)使用str()準(zhǔn)備對(duì)象用于打印。

字符串的format()方法也可以訪問這些方法。當(dāng)我們使用{!r}{!s}格式,我們分別需要__repr__()__str__()

首先讓我們看看默認(rèn)實(shí)現(xiàn)。

下面是一個(gè)簡(jiǎn)單的類層次結(jié)構(gòu):

pythonclass Card:
    insure = False
    def __init__(self, rank, suit):
        self.suit = suit
        self.rank = rank
        self.hard, self.soft = self._points()

class NumberCard(Card):
    def _points(self):
        return int(self.rank), int(self.rank)

我們已經(jīng)定義了帶有四個(gè)屬性的兩個(gè)簡(jiǎn)單類。

以下是一個(gè)與其中一個(gè)類對(duì)象的交互:

>>> x=NumberCard( "2", "?")
>>> str(x)
"<__main__.NumberCard object at 0x1013ea610>"
>>> repr(x)
"<__main__.NumberCard object at 0x1013ea610>"
>>> print(x)
<__main__.NumberCard object at 0x1013ea610>

從這個(gè)輸出知道默認(rèn)的__str__()__repr__()實(shí)現(xiàn)不是很豐富。

當(dāng)我們需要覆蓋__str__()__repr__()時(shí)我們考慮下面兩個(gè)廣泛的設(shè)計(jì)用例:

非集合對(duì)象:一個(gè)不包含其他對(duì)象集合的“簡(jiǎn)單”對(duì)象,通常不涉及非常復(fù)雜格式的集合。

集合對(duì)象:一個(gè)包含一組更復(fù)雜格式的對(duì)象。

1. 非集合__str__()__repr__()

正如我們之前看到的,__str__()__repr__()的輸出不是很豐富。我們幾乎總是需要覆蓋它們。以下是當(dāng)沒有包含集合的時(shí)候覆蓋__str__()__repr__()的方法。這些方法從屬于之前定義的Card類:

pythondef __repr__(self):
    return "{__class__.__name__}(suit={suit!r}, rank={rank!r})".format(
            __class__=self.__class__, **self.__dict__)
def __str__(self):
    return "{rank}{suit}".format(**self.__dict__)

這兩個(gè)方法依賴于傳遞內(nèi)部對(duì)象的實(shí)例變量__dict__()format()函數(shù)。對(duì)于對(duì)象使用__slots__是不適合的;通常,這些是不可變的對(duì)象。在格式說明符中使用名稱會(huì)使得格式化更顯式。當(dāng)然也使得格式模板更長(zhǎng)了。在__repr__()中,我們傳遞內(nèi)部__dict__加上對(duì)象的__class__作為關(guān)鍵字參數(shù)值給format()函數(shù)。

模板字符串使用兩種格式說明符:

{__class__.__name__}模板也可以寫成{__class__.__name__!s}從而當(dāng)只提供簡(jiǎn)單字符串的類名時(shí)變得更顯式。

{suit!r}{rank!r }模板都使用!r格式說明符生成屬性值的repr()方法。

__str__()中,我們只有傳遞內(nèi)部__dict__對(duì)象。格式化使用隱式的{!s}格式說明符來生成屬性值的str()方法。

2. 集合__str__()__repr__()

當(dāng)包含一個(gè)集合時(shí),我們需要格式化集合中的每個(gè)項(xiàng)目以及整個(gè)容器。以下是帶有__str__()__repr__()方法的簡(jiǎn)單集合:

pythonclass Hand:
    def __init__(self, dealer_card, *cards):
        self.dealer_card = dealer_card
        self.cards = list(cards)
    def __str__(self):
        return ", ".join(map(str, self.cards))
    def __repr__(self):
        return "{__class__.__name__}({dealer_card!r}, {_cards_str})".format(
                __class__=self.__class__, _cards_str=", ".join(
                map(repr, self.cards)),**self.__dict__)

__str__()方法是一個(gè)簡(jiǎn)單的設(shè)計(jì),如下:

映射str()到集合中的每一項(xiàng)。這將在生成的每個(gè)字符串值上創(chuàng)建一個(gè)迭代器。

使用", ".join()合并所有項(xiàng)的字符串到一個(gè)長(zhǎng)字符串中。

__repr__()方法是一個(gè)多部分的設(shè)計(jì),如下:

映射repr()到集合中的每一項(xiàng)。這將在生成的每個(gè)字符串值上創(chuàng)建一個(gè)迭代器。

使用", ".join()合并所有項(xiàng)的字符串。

創(chuàng)建一組帶有__class__的關(guān)鍵字、集合字符串和來自__dict__的各種屬性。我們已經(jīng)命名集合字符串為_card_str,與現(xiàn)有的屬性不沖突。

使用"{__class__.__name__}({dealer_card!r}, {_card_str})".format()將類名與項(xiàng)目值的長(zhǎng)字符串結(jié)合。我們使用!r進(jìn)行格式化以確保屬性也使用了repr()轉(zhuǎn)換。

在某些情況下,這可以使一些事情變得稍微簡(jiǎn)單些。位置參數(shù)的格式化可以一定程度上縮短模板字符串的長(zhǎng)度。

__format__() 方法

和內(nèi)置函數(shù)format()一樣,string.format()使用__format__()方法。這兩個(gè)接口都是用來從給定對(duì)象得到像樣的字符串的方式。

以下是將參數(shù)提供給__format__()的兩種方法:

someobject.__format__(""):發(fā)生在應(yīng)用程序使用format(someobject)或等價(jià)的"{0}".format(someobject)的時(shí)候。在這些情況下,提供了長(zhǎng)度為零的字符串說明符。這會(huì)產(chǎn)生一個(gè)默認(rèn)格式。

someobject.__format__(specification):發(fā)生在應(yīng)用程序使用format(someobject, specification)或等價(jià)的"{0:specification}".format(someobject)的時(shí)候。

請(qǐng)注意,類似于"{0!r}".format()"{0!s}".format()的方法沒有使用__format__()方法。它們直接使用了__repr__()__str__()

帶有""說明符的合理響應(yīng)是返回str(self)。它對(duì)各種對(duì)象的字符串提供了顯式的一致性表示。

格式說明符必須都是文本,且在格式字符串的":"之后。當(dāng)我們寫"{0:06.4f}"06.4f是適用于第0項(xiàng)參數(shù)列表的格式說明符。

Python標(biāo)準(zhǔn)庫(kù)文檔中的6.1.3.1節(jié)定義了一個(gè)復(fù)雜的數(shù)值說明符作為九個(gè)部分字符串,這是格式說明符的一種迷你語(yǔ)言。有如下語(yǔ)法:

[[fill]align][sign][#][0][width][,][.precision][type]

我們可以用正則表達(dá)式解析這些標(biāo)準(zhǔn)說明符,如下面代碼片段所示:

re.compile(
r"(?P.?[<>=^])?"
"(?P[-+ ])?"
"(?P#)?"
"(?P0)?"
"(?Pd*)"
"(?P,)?"
"(?P.d*)?"
"(?P[bcdeEfFgGnosxX%])?" )

這個(gè)正則將說明符拆分成八組。第一組和原說明符一樣有fillalignment字段。我們可以使用這些得出我們已定義類的格式化數(shù)值數(shù)據(jù)。

然而,Python的格式說明符迷你語(yǔ)言可能不適用于我們的類定義。因此,我們需要定義我們自己的說明符迷你語(yǔ)言并在類的__format__方法中執(zhí)行。如果我們定義數(shù)值類型,我們應(yīng)該堅(jiān)持預(yù)定義的迷你語(yǔ)言。然而,對(duì)于其他類型則沒有理由再堅(jiān)持預(yù)定義的語(yǔ)言。

作為一個(gè)示例,這里有個(gè)微不足道的語(yǔ)言,使用字符%r%s分別給我們展示牌值和花色。在結(jié)果字符串中%%字符變成%。所有其他字符是重復(fù)的。

我們可以通過格式化擴(kuò)展我們的Card類,如下面代碼片段所示:

pythondef __format__(self, format_spec):
    if format_spec == "":
        return str(self)
    rs = format_spec.replace("%r", self.rank).replace("%s", self.suit)
    rs = rs.replace("%%", "%")
    return rs

這個(gè)定義會(huì)檢查格式說明符。如果沒有說明符,則使用str()函數(shù)。如果提供了一個(gè)說明符,會(huì)合攏牌值、花色和任何%字符格式說明符,將其轉(zhuǎn)化為輸出字符串。

這允許我們像下面這樣格式化Card

pythonprint( "Dealer Has {0:%r of %s}".format(hand.dealer_card))

格式說明符("%r of %s")被作為format的參數(shù)傳遞給我們的__format__()方法。使用這個(gè),我們能夠提供一個(gè)一致的接口來表示我們已經(jīng)定義的類的對(duì)象。

或者,我們可以定義如下:

pythondefault_format = "some specification"
def __str__(self):
    return self.__format__(self.default_format)
def __format__(self, format_spec):
    if format_spec == "":  
        format_spec = self.default_format
    # process the format specification.

這個(gè)的優(yōu)勢(shì)在于把所有字符串放置到__format__()方法,而不是分開到的__format__()__str__()。劣勢(shì)在于,我們不總是需要實(shí)現(xiàn)__format__(),但我們幾乎總是需要實(shí)現(xiàn)__str__()

1. 嵌套格式化說明符

string.format()方法可以處理嵌套的{}實(shí)例來執(zhí)行簡(jiǎn)單的關(guān)鍵字置換到格式說明符中。這個(gè)置換完成,會(huì)創(chuàng)建最終格式字符串并傳遞給類的__format__()方法。這種嵌套置換通過參數(shù)化通用說明符簡(jiǎn)化了某些相對(duì)復(fù)雜的數(shù)值格式。

下面的例子,我們可以在format參數(shù)中很容易的修改width

pythonwidth = 6
for hand, count in statistics.items():
    print( "{hand} {count:{width}d}".format(hand=hand, count=count, width=width))

我們定義了一個(gè)通用的格式,"{hand:%r%s } {count:{width}d}",這需要一個(gè)width參數(shù)讓它變成適用的格式說明符。

format()方法提供width=參數(shù)的值被用于替代{width}嵌套說明符。一旦被替換,最終格式會(huì)作為一個(gè)整體提供給__format__()方法。

2. 集合與委托格式說明符

格式化一個(gè)包括集合的復(fù)雜對(duì)象,有兩個(gè)格式化問題:如何格式化整體對(duì)象以及如何格式化集合中的項(xiàng)目。當(dāng)我們看到Hand,例如,我們看到我們有多帶帶的Card類集合。我們需要Hand委托格式化細(xì)節(jié)給多帶帶的Card實(shí)例。

下面是一個(gè)適用于Hand__format__()方法:

pythondef __format__(self, format_specification):
    if format_specification == "":
        return str(self)
    return ", ".join("{0:{fs}}".format(c, fs=format_specification) for c in self.cards)

format_specification參數(shù)將用于每個(gè)Hand集合里面的Card實(shí)例。格式說明符"{0:{fs}}"使用嵌套格式說明符技術(shù)將format_specification字符串置入到應(yīng)用于Card實(shí)例的創(chuàng)建。使用這種方法我們可以格式化Hand對(duì)象、player_hand,如下所示:

python"Player: {hand:%r%s}".format(hand=player_hand)

這將應(yīng)用%r%s格式說明符到Hand對(duì)象中的Card實(shí)例。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/45391.html

相關(guān)文章

  • [] Python 無縫集成——基本特殊方法 3

    摘要:比較運(yùn)算符方法有六個(gè)比較運(yùn)算符。根據(jù)文檔,其映射工作如下第七章創(chuàng)建數(shù)字我們會(huì)再次回到比較運(yùn)算符這塊。同一個(gè)類的對(duì)象的比較實(shí)現(xiàn)我們來看看一個(gè)簡(jiǎn)單的同一類的比較通過觀察一個(gè)更完整的類現(xiàn)在我們已經(jīng)定義了所有六個(gè)比較運(yùn)算符。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __bool__()方法 Python對(duì)假有個(gè)很...

    2json 評(píng)論0 收藏0
  • [] Python 無縫集成——基本特殊方法 2

    摘要:有三個(gè)用例通過和方法定義相等性檢測(cè)和值不可變對(duì)象對(duì)于有些無狀態(tài)對(duì)象,例如這些不能被更新的類型。請(qǐng)注意,我們將為不可變對(duì)象定義以上兩個(gè)。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __hash__() 方法 內(nèi)置hash()函數(shù)會(huì)調(diào)用給定對(duì)象的__hash__()方法。這里hash就是將(可能是復(fù)雜的)值縮減...

    hzc 評(píng)論0 收藏0
  • [] Python 無縫集成——基本特殊方法 4

    摘要:當(dāng)引用計(jì)數(shù)為零,則不再需要該對(duì)象且可以銷毀。這表明當(dāng)變量被刪除時(shí)引用計(jì)數(shù)正確的變?yōu)榱恪7椒ㄖ荒茉谘h(huán)被打破后且引用計(jì)數(shù)已經(jīng)為零時(shí)調(diào)用。這兩步的過程允許引用計(jì)數(shù)或垃圾收集刪除已引用的對(duì)象,讓弱引用懸空。這允許在方法設(shè)置對(duì)象屬性值之前進(jìn)行處理。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __del__()方法 ...

    Allen 評(píng)論0 收藏0
  • Python無縫集成----基本特殊方法.(Mastering Objecting-orient

    摘要:第二章與的無縫集成基本特殊方法筆記中有有一些特殊的方法它們?cè)试S我們的類和更好的集成和方法通常方法表示的對(duì)象對(duì)用戶更加友好這個(gè)方法是有對(duì)象的方法實(shí)現(xiàn)的什么時(shí)候重寫跟非集合對(duì)象一個(gè)不包括其他集合對(duì)象的簡(jiǎn)單對(duì)象這類對(duì)象格式通常不會(huì)特別復(fù) 第二章 與Python的無縫集成----基本特殊方法.(Mastering Objecting-oriented Python 筆記) python中有有一...

    iamyoung001 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<