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

資訊專欄INFORMATION COLUMN

[譯] 與 Python 無(wú)縫集成——基本特殊方法 3

2json / 1043人閱讀

摘要:比較運(yùn)算符方法有六個(gè)比較運(yùn)算符。根據(jù)文檔,其映射工作如下第七章創(chuàng)建數(shù)字我們會(huì)再次回到比較運(yùn)算符這塊。同一個(gè)類的對(duì)象的比較實(shí)現(xiàn)我們來(lái)看看一個(gè)簡(jiǎn)單的同一類的比較通過(guò)觀察一個(gè)更完整的類現(xiàn)在我們已經(jīng)定義了所有六個(gè)比較運(yùn)算符。

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

__bool__()方法

Python對(duì)假有個(gè)很好的定義。參考手冊(cè)列出了大量的值來(lái)被檢測(cè)為False。這包括諸如:False0""[](){}。大多數(shù)其他對(duì)象將被檢測(cè)為True

通常,我們會(huì)用一個(gè)簡(jiǎn)單的語(yǔ)句檢查一個(gè)對(duì)象“不空”,如下所示:

if some_object:
    process(some_object)

隱藏在內(nèi)部的是內(nèi)置函數(shù)__bool__()的工作。這個(gè)函數(shù)依賴于一個(gè)給定對(duì)象的__bool__()方法。

默認(rèn)的__bool__()方法返回True。我們可以看如下代碼:

>>> x = object()
>>> bool(x)
True

對(duì)于大多數(shù)類,這是非常有效的。大多數(shù)對(duì)象不會(huì)是False。然而,對(duì)于集合這是不合適的。空集合應(yīng)該相當(dāng)于False。非空集合則返回True。我們可能需要添加一個(gè)這樣的方法到我們的Deck對(duì)象。

如果我們包裝一個(gè)列表,我們需要如下操作:

def __bool__(self):
    return bool(self._cards)

它委托布爾函數(shù)到內(nèi)部_cards集合。

如果我們擴(kuò)展列表,我們需要如下操作:

def __bool__(self):
    return super().__bool__(self)

它委托到__bool__()函數(shù)的超類定義。

在這兩種情況下,我們特意地委托布爾檢測(cè)。在包裝那個(gè)例子,我們委托給集合。在擴(kuò)展的例子,我們委托給超類。無(wú)論哪種方式,包裝或擴(kuò)展,空集合將是False。這將給我們一種途徑去看Deck對(duì)象是否已經(jīng)完全處理完且是空的。

我們可以按照如下代碼片段所示去做:

d = Deck()
while d:
  card= d.pop()
  # process the card

此循環(huán)將處理所有的牌,在整副牌都沒(méi)有了的時(shí)候不會(huì)出現(xiàn)IndexError異常。

__bytes__()方法

有時(shí)候會(huì)出現(xiàn)將一個(gè)對(duì)象轉(zhuǎn)換成字節(jié)的情況。我們將在第2部分《持久化和序列化》中詳細(xì)看看相關(guān)內(nèi)容。

在最常見(jiàn)的情況下,應(yīng)用程序可以創(chuàng)建一個(gè)字符串表示,Python IO類內(nèi)置的編碼功能可以將字符串轉(zhuǎn)換成字節(jié)。幾乎任何情況下都能完成的很好。唯一的例外是當(dāng)我們定義了一種新的字符串。在這種情況下,我們需要定義該字符串編碼。

bytes()函數(shù)可以做很多事情,但這取決于它的參數(shù):

bytes(integer):返回給定整數(shù)個(gè)0x00的不可變字節(jié)對(duì)象。

bytes(string):將給定字符串編碼成字節(jié)。額外的編碼參數(shù)和錯(cuò)誤處理將定義編碼處理的細(xì)節(jié)。

bytes(something):這將調(diào)用something.__bytes__()來(lái)創(chuàng)建一個(gè)字節(jié)對(duì)象。這里將不會(huì)使用編碼或錯(cuò)誤參數(shù)。

基本object類沒(méi)有定義__bytes__()。這意味著我們的類默認(rèn)不提供__bytes__()方法。

有一些特殊的情況下,我們可能需要有一個(gè)在寫入到文件之前被直接編碼到字節(jié)中的對(duì)象。通常是簡(jiǎn)單的字符串并允許str類型為我們生成字節(jié)。在處理字節(jié)時(shí),重要的是要注意,沒(méi)有簡(jiǎn)單的方法從文件或接口來(lái)解碼。內(nèi)置的bytes類只會(huì)解碼字符串,不是我們獨(dú)有的新對(duì)象。我們可能需要從字節(jié)解碼來(lái)解析字符串。或者,我們可能需要使用struct模塊顯式地解析字節(jié),通過(guò)解析好的值創(chuàng)建獨(dú)有對(duì)象。

我們看看編碼和解碼Card成字節(jié)。有52個(gè)牌值,每張牌可以打包到一個(gè)字節(jié)。然而,我們已經(jīng)選擇使用一個(gè)字符代表suit和一個(gè)字符來(lái)表示rank。此外,我們需要正確地重構(gòu)Card子類,所以我們必須編碼幾件事情:

Card(AceCard, NumberCard, FaceCard)子類

子類定義的__init__()的參數(shù)

注意,我們的替代方法__init__()將一個(gè)牌值轉(zhuǎn)換成一個(gè)字符串,失去原來(lái)的數(shù)值。為了一個(gè)可逆的字節(jié)編碼,我們需要重構(gòu)這個(gè)原始牌值。

下面是__bytes__()的實(shí)現(xiàn),它返回一個(gè)utf-8編碼的Cards類、ranksuit

def __bytes__(self):
    class_code = self.__class__.__name__[0]
    rank_number_str = {"A": "1", "J": "11", "Q": "12", "K": "13"}.
      get(self.rank, self.rank)
    string = "("+" ".join([class_code, rank_number_str, self.suit,]) + ")"
    return bytes(string, encoding="utf8")

以上通過(guò)創(chuàng)建一個(gè)Card對(duì)象的字符串表示,然后編碼字符串到字節(jié)才能起作用。這通常是最簡(jiǎn)單、最靈活的方法。

當(dāng)我們有一堆字節(jié)的時(shí)候,可以解碼字符串,然后將字符串解析到新的Card對(duì)象。下面是一個(gè)可以用于從字節(jié)創(chuàng)建一個(gè)Card對(duì)象的方法:

def card_from_bytes(buffer):
    string = buffer.decode("utf8")
    assert string[0] == "(" and string[-1] == ")"
    code, rank_number, suit = string[1:-1].split()
    class_ = {"A": AceCard, "N": NumberCard, "F": FaceCard}[code]
    return class_(int(rank_number), suit)

在前面的代碼中,我們將字節(jié)解碼為一個(gè)字符串。然后我們將該字符串解析為各個(gè)值。從這些值,我們可以定位類且構(gòu)建原始Card對(duì)象。

我們可以構(gòu)建Card對(duì)象的字節(jié)表示,如下:

b = bytes(someCard)

我們可以通過(guò)字節(jié)重構(gòu)Card對(duì)象,如下:

someCard = card_from_bytes(b)

重要的是要注意,外部字節(jié)表示通常是具有挑戰(zhàn)性的設(shè)計(jì)。我們創(chuàng)建一個(gè)對(duì)象狀態(tài)表示。Python已經(jīng)有很多對(duì)我們類定義工作的很好的表示。

通常是使用picklejson模塊比發(fā)明低級(jí)的字節(jié)來(lái)表示一個(gè)對(duì)象要更好。這是第九章《序列化和存儲(chǔ)JSON、YAML、Pickle、CSV和XML》的主要內(nèi)容。

比較運(yùn)算符方法

Python有六個(gè)比較運(yùn)算符。這些操作符有特殊的方法實(shí)現(xiàn)。根據(jù)文檔,其映射工作如下:

x < y calls x.__lt__(y)

x <= y calls x.__le__(y)

x == y calls x.__eq__(y)

x != y calls x.__ne__(y)

x > y calls x.__gt__(y)

x >= y calls x.__ge__(y)

第七章《創(chuàng)建數(shù)字》我們會(huì)再次回到比較運(yùn)算符這塊。

有一些關(guān)于哪個(gè)操作符被真實(shí)實(shí)現(xiàn)的額外規(guī)則。這些規(guī)則是基于左邊對(duì)象的類所需的特殊方法。如果沒(méi)有,Python可以改變順序來(lái)嘗試另一種操作。

這里有兩個(gè)基本規(guī)則

首先,左邊的操作數(shù)是由操作符的實(shí)現(xiàn)方法來(lái)檢查的:A < B意味著A.__lt__(B)

第二,右邊的操作數(shù)是由相反的操作符的實(shí)現(xiàn)方法來(lái)檢查的:A < B意味著B.__gt__(A)

罕見(jiàn)的例外發(fā)生在右操作數(shù)是左操作數(shù)的一個(gè)子類;然后,右操作數(shù)是第一個(gè)被檢查的,允許子類覆蓋超類。

我們可以看到這是如何工作的當(dāng)一個(gè)類只有一個(gè)操作符的時(shí)候,然后供其他操作符使用。

以下是我們可以使用的部分類:

class BlackJackCard_p:

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __lt__(self, other):
        print("Compare {0} < {1}".format(self, other))
        return self.rank < other.rank

    def __str__(self):
        return "{rank}{suit}".format(**self.__dict__)

這是21點(diǎn)的比較規(guī)則,花色不重要。我們省略了比較的方法來(lái)了解當(dāng)操作符丟失的時(shí)候Python是如何撤回的。這個(gè)類允許我們執(zhí)行<比較。有趣的是,Python還可以通過(guò)切換參數(shù)順序來(lái)使用>比較。換句話說(shuō),x < y ≡ y > x。這是鏡像反射規(guī)則;我們將在第七章《創(chuàng)造數(shù)字》再次見(jiàn)到它。

我們將看到試圖評(píng)估不同的比較操作。創(chuàng)建兩個(gè)Cards類且比以不同的方式較它們,如下代碼片段所示:

>>> two = BlackJackCard_p(2, "?")
>>> three = BlackJackCard_p(3, "?")
>>> two < three
Compare 2? < 3?
True
>>> two > three
Compare 3? < 2?
False
>>> two == three
False
>>> two <= three
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unorderable types: BlackJackCard_p() <= BlackJackCard_p()

從這,我們可以看到two < three映射到two.__lt__(three)

然而,對(duì)于two > three、沒(méi)有__gt__()方法定義;Python使用three.__lt__(two)作為一個(gè)后備計(jì)劃。

默認(rèn)情況下,__eq__()方法是繼承自object;它比較對(duì)象ID;對(duì)象將有==!=檢測(cè),如下:

>>> two_c = BlackJackCard_p(2, "?")
>>> two == two_c
False

我們可以看到結(jié)果并不是我們所期待的。我們會(huì)經(jīng)常需要覆蓋默認(rèn)的__eq__()實(shí)現(xiàn)。

同樣,操作符之間沒(méi)有邏輯聯(lián)系。在數(shù)學(xué)上,只要兩個(gè)就可以派生所有必要的比較。Python不會(huì)自動(dòng)這樣做。相反,Python默認(rèn)處理以下四對(duì)相反的檢測(cè):

x < y ≡ y > x
x ≤ y ≡ y ≥ x
x = y ≡ y = x
x =? y ≡ y =? x

這意味著我們必須至少?gòu)乃膶?duì)中提供一個(gè)。例如,我們可以提供__eq__()__ne__()__lt__()__le__()

@functools.total_ordering裝飾器克服了默認(rèn)限制,并從__eq__()__lt__()__le__()__gt__()中任意的一個(gè),推導(dǎo)出其余的比較。我們將在第7章《創(chuàng)造數(shù)字》再次討論這個(gè)。

1. 設(shè)計(jì)比較

在比較運(yùn)算符有兩個(gè)顧慮:

顯而易見(jiàn)的問(wèn)題是怎樣比較相同類的兩個(gè)對(duì)象

不太明顯的問(wèn)題是怎樣比較不同類的對(duì)象

對(duì)于一個(gè)類有多個(gè)屬性,我們考慮比較運(yùn)算符的時(shí)候經(jīng)常模棱兩可。可能不是很清楚我們要比較什么。

再次考慮不起眼的撲克牌。表達(dá)式如card1 == card2顯然是為了比較ranksuit。對(duì)嗎?或者總是為真?終究,suit在21點(diǎn)沒(méi)有意義。

如果我們想決定Hand對(duì)象是否可以分牌,我們最好看下這兩個(gè)代碼片段。以下是第一個(gè)代碼片段:

if hand.cards[0] == hand.cards[1]

下面是第二個(gè)代碼片段:

if hand.cards[0].rank == hand.cards[1].rank

雖然有一個(gè)是更短,簡(jiǎn)潔并不總是最好的。如果我們定義相等只考慮rank,我們將很難定義單元測(cè)試,因?yàn)楫?dāng)一個(gè)單元測(cè)試應(yīng)該關(guān)注完全正確的牌時(shí),一個(gè)簡(jiǎn)單的TestCase.assertEqual()方法會(huì)容忍各種各樣的牌。

表達(dá)式如card1 < = 7顯然是為了比較rank

我們想要一些比較來(lái)比較牌的所有屬性,一些比較比較rank?我們?cè)撛鯓油ㄟ^(guò)suit來(lái)排序?此外,相等性的比較必須并行計(jì)算hash。如果我們?cè)趆ash中包含多個(gè)屬性,我們需要將其包含在相等性的比較中。在這種情況下,似乎牌之間的相等和不相等必須全部的Card比較,因?yàn)槲覀兊膆ash包括了ranksuit

Card之間的比較順序,無(wú)論如何都應(yīng)該只有rank。和整數(shù)的比較同樣也應(yīng)該只有rank。當(dāng)發(fā)現(xiàn)分牌這一特殊情況,hand.cards[0].rank == hand.cards[1].rank會(huì)處理的很好,因?yàn)樵诜峙埔?guī)則中它是顯式的。

2. 同一個(gè)類的對(duì)象的比較實(shí)現(xiàn)

我們來(lái)看看一個(gè)簡(jiǎn)單的同一類的比較通過(guò)觀察一個(gè)更完整的BlackJackCard

class BlackJackCard:

    def __init__(self, rank, suit, hard, soft):
        self.rank = rank
        self.suit = suit
        self.hard = hard
        self.soft = soft

    def __lt__(self, other):
        if not isinstance( other, BlackJackCard ):
            return NotImplemented
        return self.rank < other.rank

    def __le__(self, other):
        try:
            return self.rank <= other.rank
        except AttributeError:
            return NotImplemented

    def __gt__(self, other):

        if not isinstance(other, BlackJackCard):
            return NotImplemented
        return self.rank > other.rank

    def __ge__(self, other):
        if not isinstance(other, BlackJackCard):
            return NotImplemented
        return self.rank >= other.rank

    def __eq__(self, other):
        if not isinstance(other, BlackJackCard):
            return NotImplemented
        return self.rank == other.rank and self.suit == other.suit

    def __ne__(self, other):
        if not isinstance(other, BlackJackCard):
            return NotImplemented
        return self.rank != other.rank and self.suit != other.suit

    def __str__(self):
        return "{rank}{suit}".format(**self.__dict__)

現(xiàn)在我們已經(jīng)定義了所有六個(gè)比較運(yùn)算符。

我們已經(jīng)向您展示了兩種類型檢查:顯式隱式。顯式類型檢查使用isinstance()。隱式類型檢查使用try:塊。使用try:塊有概念上的小優(yōu)勢(shì),它能避免重復(fù)的類名。有可能會(huì)有人想發(fā)明一種變體牌來(lái)兼容BlackJackCard但不是定義為適當(dāng)?shù)淖宇悺J褂?b>isinstance()可以防止一個(gè)無(wú)效類來(lái)保證工作正常。

try:塊會(huì)允許一個(gè)類使用rank屬性。這變成一個(gè)難以解決問(wèn)題的風(fēng)險(xiǎn)會(huì)變?yōu)榱悖鳛轭愒趹?yīng)用程序的其他地方可能會(huì)失敗。同樣,Card實(shí)例與金融建模應(yīng)用程序類比較出現(xiàn)根據(jù)牌值排序的屬性。

在接下來(lái)的例子中,我們將關(guān)注try:塊。isinstance()方法檢查一直是Python慣用方法且應(yīng)用廣泛。我們通過(guò)顯式地返回NotImplemented來(lái)告知Python,這個(gè)操作符并不是用來(lái)實(shí)現(xiàn)這種類型數(shù)據(jù)的。Python可以顛倒參數(shù)順序來(lái)看看另一個(gè)操作數(shù)是否提供了實(shí)現(xiàn)方法。如果沒(méi)有找到有效的操作符,則TypeError異常將被拋出。

我們省略了三個(gè)子類定義和工廠函數(shù),留下card21()作為一個(gè)練習(xí)。

我們也省略了同類的比較,我們將在下一節(jié)看到。通過(guò)這個(gè)類,我們可以成功的比較牌。下面是一個(gè)例子,我們創(chuàng)建并比較三張牌:

>>> two = card21(2, "?")
>>> three = card21(3, "?")
>>> two_c = card21(2, "?")

根據(jù)這些Cards類,我們可以進(jìn)行一些比較,如下代碼片段所示:

>>> two == two_c
False
>>> two.rank == two_c.rank
True
>>> two < three
True
>>> two_c < three
True

定義似乎和預(yù)期的一樣。

3. 混合類對(duì)象的比較實(shí)現(xiàn)

我們使用BlackJackCard類為例,當(dāng)我們嘗試比較來(lái)自不同類的兩個(gè)操作數(shù)時(shí),看看會(huì)發(fā)生什么。

下面是Card實(shí)例,我們可以和int值相比較:

>>> two = card21(2, "?")
>>> two < 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unorderable types: Number21Card() < int()
>>> two > 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unorderable types: Number21Card() > int()

這就是我們期望的,BlackJackCardNumber21Card的子類沒(méi)有提供所需的特殊方法,所以有TypeError異常。

然而,考慮下面的兩個(gè)例子:

>>> two == 2
False
>>> two == 3
False

為什么是這樣的結(jié)果?當(dāng)面臨一個(gè)NotImplemented值,Python會(huì)對(duì)調(diào)操作數(shù)。在這種情況下,整數(shù)值定義int.__eq__()方法,容忍一個(gè)意想不到的類對(duì)象。

4. Hard點(diǎn)數(shù)、Soft點(diǎn)數(shù)和多態(tài)性

我們定義Hand這樣它將執(zhí)行一些有意義的混合類比較。與其他的比較,我們必須確定這正是我們要比較的。

對(duì)于Hands之間的相等比較,我們應(yīng)該比較所有牌。

對(duì)于Hands比較順序,我們需要比較每個(gè)Hand對(duì)象的一個(gè)屬性。為了逐個(gè)和int相比較,我們應(yīng)該讓Hand對(duì)象的總數(shù)逐個(gè)相比較。為了有一個(gè)總數(shù),在21點(diǎn)游戲中我們必須分類hard點(diǎn)數(shù)和soft點(diǎn)數(shù)。

當(dāng)有一個(gè)A在手,會(huì)有下面兩個(gè)候選點(diǎn)數(shù):

soft點(diǎn)數(shù)把A當(dāng)作11。如果soft點(diǎn)數(shù)超過(guò)21,那么A當(dāng)作1。

hard點(diǎn)數(shù)把A當(dāng)作1。

這意味著手牌的總和不是簡(jiǎn)單的牌的總和。

首先我們必須確定是否有一個(gè)A在手。確定這些,我們可以確定是否有一個(gè)有效的(小于或等于21)的soft點(diǎn)數(shù)。否則,我們將依靠hard點(diǎn)數(shù)。

多態(tài)性的一個(gè)癥狀是依靠isinstance()來(lái)確定子類的成員。一般來(lái)說(shuō),這違反了基本的封裝特性。一組好的多態(tài)的子類定義應(yīng)該完全對(duì)等且?guī)в邢嗤姆椒ê灻@硐肭闆r下,類的定義是不透明的,我們不需要看類的內(nèi)部定義。一組多態(tài)的類使用廣泛的isinstance()檢測(cè)。在某些情況下,isinstance()是必要的。當(dāng)使用一個(gè)內(nèi)置類的時(shí)候都會(huì)出現(xiàn)這樣。我們不能追溯添加方法函數(shù)到內(nèi)置類中,子類化它們來(lái)添加一個(gè)多態(tài)性輔助方法可能是不值得的。

對(duì)于一些特殊的方法,有必要看到isinstance()用于實(shí)現(xiàn)跨多個(gè)類對(duì)象的操作,沒(méi)有簡(jiǎn)單的繼承層次結(jié)構(gòu)。在下一節(jié),與之無(wú)關(guān)的類中,我們將向您展示isinstance()的慣用方法。

對(duì)于我們牌的類層次結(jié)構(gòu),我們想要一個(gè)方法(或?qū)傩?來(lái)標(biāo)識(shí)A,而不是用isinstance()。這是一個(gè)多態(tài)輔助方法。它確保我們可以辨別否則等價(jià)類會(huì)分開。

我們有兩個(gè)選擇:

添加一個(gè)類級(jí)別的屬性

添加一個(gè)方法

因?yàn)楸J氐馁€注方式,我們有兩個(gè)原因去檢查A。如果莊家的牌是A,它會(huì)觸發(fā)一個(gè)保險(xiǎn)的賭注。如果莊家手牌(或玩家的手牌)有一個(gè)A,會(huì)有一個(gè)soft點(diǎn)數(shù)與hard點(diǎn)數(shù)的計(jì)算。

hard點(diǎn)數(shù)和soft點(diǎn)數(shù)是card.soft - card.hard值的差。我們可以在AceCard里面的定義看到這個(gè)值是10。然而,深入類的內(nèi)部可以看到該實(shí)現(xiàn)違背了封裝性。

我們可以將BlackjackCard作為透明的,然后檢查card.soft - card.hard != 0是否為真。如果為真,這些信息足夠算出hard點(diǎn)數(shù)和soft點(diǎn)數(shù)。

下面是一個(gè)使用total方法計(jì)算soft值和hard值之間差值的版本:

def total(self):
    delta_soft = max(c.soft-c.hard for c in self.cards)
    hard = sum(c.hard for c in self.cards)
    if hard+delta_soft <= 21:
        return hard+delta_soft
    return hard

我們將計(jì)算hard點(diǎn)數(shù)和soft點(diǎn)數(shù)差作為delta_soft。對(duì)于大多數(shù)牌,差異是零。對(duì)于A,差異是非零。

鑒于hard點(diǎn)數(shù)和delta_soft,我們可以確定返回那個(gè)總數(shù)。如果是hard + delta_soft小于或等于21,值是soft點(diǎn)數(shù)。如果soft點(diǎn)數(shù)大于21,又恢復(fù)到hard點(diǎn)數(shù)。

我們可以考慮讓值21為顯式常量。一個(gè)有意義的名字有時(shí)比文字更有幫助。因?yàn)?1點(diǎn)的規(guī)則,21不太可能會(huì)改變到一個(gè)不同的值。沒(méi)有比文字含義的21更有意義的了。

5. 混合類比較示例

Hand對(duì)象給定一個(gè)點(diǎn)數(shù),我們可以有意義地定義Hand實(shí)例之間的比較以及Handint之間的對(duì)比。為了確定我們做哪一種比較,我們被迫使用isinstance()

以下是部分Hand比較的定義:

class 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__)

    def __eq__(self, other):
        if isinstance(other, int):
            return self.total() == other
        try:
            return (self.cards == other.cards and self.dealer_card == other.dealer_card)
        except AttributeError:
            return NotImplemented

    def __lt__(self, other):
        if isinstance(other, int):
            return self.total() < other
        try:
            return self.total() < other.total()
        except AttributeError:
            return NotImplemented

    def __le__(self, other):
        if isinstance(other, int):
            return self.total() <= other
        try:
            return self.total() <= other.total()
        except AttributeError:
            return NotImplemented

       __hash__ = None

    def total(self):
        delta_soft = max(c.soft-c.hard for c in self.cards)
        hard = sum(c.hard for c in self.cards)
        if hard+delta_soft <= 21:
            return hard+delta_soft
        return hard

我們定義了三個(gè)比較,不是所有的六個(gè)。

為了與Hand交互我,們需要幾個(gè)Card對(duì)象:

>>> two = card21(2, "?")
>>> three = card21(3, "?")
>>> two_c = card21(2, "?")
>>> ace = card21(1, "?")
>>> cards = [ace, two, two_c, three]

我們將使用這個(gè)序列的牌來(lái)看看兩個(gè)不同的hand實(shí)例。

第一個(gè)Hands對(duì)象有一個(gè)無(wú)關(guān)緊要的莊家的Card對(duì)象和先前創(chuàng)建的四張牌。Card對(duì)象中的一個(gè)是A:

>>> h= Hand(card21(10,"?"), *cards)
>>> print(h)
A?, 2?, 2?, 3?
>>> h.total()
18

soft點(diǎn)數(shù)是18,hard點(diǎn)數(shù)是8。

下面是第二個(gè)對(duì)象,有一個(gè)額外的Card對(duì)象:

>>> h2= Hand(card21(10,"?"), card21(5,"?"), *cards)
>>> print(h2)
5?, A?, 2?, 2?, 3?
>>> h2.total()
13

hard點(diǎn)數(shù)是13。沒(méi)有soft點(diǎn)數(shù),因?yàn)樗^(guò)了21。

Hands之間的比較工作得很好,如下代碼片段所示:

>>> h < h2
False
>>> h > h2
True

我們基于比較運(yùn)算符對(duì)Hands進(jìn)行排名。

我們也可以讓Hands與整數(shù)進(jìn)行比較,如下代碼片段所示:

>>> h == 18
True
>>> h < 19
True
>>> h > 17
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unorderable types: Hand() > int()

只要與整數(shù)的比較正常工作,Python不會(huì)被迫撤回。前面的例子告訴我們當(dāng)沒(méi)有__gt__()方法。Python檢查相反的操作數(shù),對(duì)于Hand整數(shù)17也沒(méi)有適當(dāng)?shù)?b>__lt__()方法。

我們可以添加必要的__gt__()__ge__()函數(shù)使得Hand與整數(shù)正常工作。

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

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

相關(guān)文章

  • [] Python 無(wú)縫集成——基本特殊方法 1

    摘要:這些基本的特殊方法在類中定義中幾乎總是需要的。和方法對(duì)于一個(gè)對(duì)象,有兩種字符串表示方法。這些都和內(nèi)置函數(shù)以及方法緊密結(jié)合。帶有說(shuō)明符的合理響應(yīng)是返回。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python 有許多特殊方法允許類與Python緊密結(jié)合,標(biāo)準(zhǔn)庫(kù)參考將其稱之為基本,基礎(chǔ)或本質(zhì)可能是更好的術(shù)語(yǔ)。這些特殊...

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

    摘要:有三個(gè)用例通過(guò)和方法定義相等性檢測(cè)和值不可變對(duì)象對(duì)于有些無(wú)狀態(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 無(wú)縫集成——基本特殊方法 4

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

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

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

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

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

0條評(píng)論

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