亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

Python 面向?qū)ο缶幊讨改?讀書(shū)筆記

cncoder / 1840人閱讀

摘要:可以賦值對(duì)象的生命周期主要是有創(chuàng)建初始化銷(xiāo)毀。顯示而非隱式對(duì)于每個(gè)方法,都應(yīng)當(dāng)顯示的制定要初始化的變量。每當(dāng)創(chuàng)建一個(gè)對(duì)象,會(huì)創(chuàng)建一個(gè)空對(duì)象,然后調(diào)用該對(duì)象的函數(shù),提供了初始化的操作。以點(diǎn)為例作為說(shuō)明。

第一部分 用特殊方法實(shí)現(xiàn)Python風(fēng)格的類(lèi)

為了實(shí)現(xiàn)更好的可擴(kuò)展性,Python語(yǔ)言提供了大量的特殊方法,它們大致分為以下幾類(lèi)。

特性訪問(wèn)

可調(diào)用對(duì)象

集合

數(shù)字

上下文

迭代器

第一章 使用__init()__方法

Python中一切事物皆對(duì)象?。。。。?!
__init__()方法記住兩點(diǎn):

__init()__(初始化)是對(duì)象生命周期的開(kāi)始,每個(gè)對(duì)象必須正確初始化才能夠正常的工作。

__init__()可以賦值

對(duì)象的生命周期主要是有創(chuàng)建、初始化、銷(xiāo)毀。
‘顯示而非隱式’:對(duì)于每個(gè)__init__()方法,都應(yīng)當(dāng)顯示的制定要初始化的變量。
每當(dāng)創(chuàng)建一個(gè)對(duì)象,python會(huì)創(chuàng)建一個(gè)空對(duì)象,然后調(diào)用該對(duì)象的__init__()函數(shù),提供了初始化的操作。

# 以21點(diǎn)為例作為說(shuō)明。
class Card(object):
    def __init__(self, suit, rank):
        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)


class AceCard(Card):
    def _points(self):
        return 1, 11


class FaceCard(Card):
    def _points(self):
        return 10, 10
   
class Suit(object):
    def __init__(self,name,symbol):
        self.name = name
        self.symbol = symbol

Club,Diamond,Heart,Spade = Suit("Club","?"),Suit("Diamond","?"),Suit("Heart","?"),Suit("Spade","?")
通過(guò)工廠函數(shù)來(lái)調(diào)用__init__():
def card(rank, suit):
    if rank == 1:
        return AceCard("A", suit)
    elif 2 <= rank < 11:
        return NumberCard(str(rank), suit)
    elif 11 <= rank < 14:
        name = {11: "J", 12: "Q", 13: "K"}[rank]
        return FaceCard(name, suit)
    else:
        raise Exception("rank out of range")
 這個(gè)函數(shù)通過(guò)傳入牌面值rank 和花色值suit來(lái)創(chuàng)建card對(duì)象.
deck = [card(rank, suit) for rank in range(1, 14) for suit in (Club, Diamond, Heart, Spade)]
print(deck[0].rank,deck[0].suit.symbol)

這段代碼完成了52張牌對(duì)象的創(chuàng)建.

使用映射和類(lèi)來(lái)簡(jiǎn)化設(shè)計(jì).

由于類(lèi)是第一級(jí)別的對(duì)象,從rank參數(shù)射到對(duì)象是很容易的事情.
下面的Card類(lèi)工廠就是使用映射實(shí)現(xiàn)的版本.

def card4(rank,suit):
    class_ = {1:AceCard,11:FaceCard,12:FaceCard,13:FaceCard}.get(rank,NumberCard)
    return class_(rank,suit)

需要修改映射邏輯,除了提供Card子類(lèi),還需要提供rank對(duì)象的字符串結(jié)果.如何實(shí)現(xiàn)這兩部分映射,有四種常見(jiàn)方案.

可以建立兩個(gè)并行映射

可以映射為一個(gè)二元組.

可以映射為partial()函數(shù).

可以考慮修改類(lèi)定義的完成映射邏輯.

1.并行映射

def card5(rank,suit):
    class_ = {1:AceCard,11:FaceCard,12:FaceCard,13:FaceCard}.get(rank,NumberCard)
    rank_str = {1:"A",11: "J", 12: "Q", 13: "K"}.get(rank,str(rank))
    return class_(rank_str,suit)

這樣是不值得做的,帶來(lái)映射鍵1,11,12,13的邏輯重復(fù).

不要使用并行結(jié)構(gòu),并行結(jié)構(gòu)應(yīng)該被元祖或者一些更好的組合所代替

映射到一個(gè)牌面值的元組

def card6(rank,suit):
   class_,rank_str= {
       1:(AceCard,"A"),
       11:(FaceCard,"J"),
       12:(FaceCard,"Q"),
       13:(FaceCard,"K")
   }.get(rank,(NumberCard,str(rank)))
   
   return class_(rank_str,suit)

從rank值映射到類(lèi)對(duì)象時(shí)很少見(jiàn)的,而且兩個(gè)參數(shù)只有一個(gè)用于對(duì)象的初始化.從rank映射到一個(gè)相對(duì)簡(jiǎn)單的類(lèi)或者是函數(shù)對(duì)象,而不必提供目的不明確的參數(shù),這才是明智的選擇.

3.partial 函數(shù)設(shè)計(jì)

def card7(rank,suit):
  from  functools import partial
  part_class = {
      1:partial(AceCard,"A"),
      11:partial(FaceCard,"J"),
      12:partial(FaceCard,"Q"),
      13:partial(FaceCard,"K")
  }.get(rank,partial(NumberCard,str(rank)))

  return part_class(suit)

通過(guò)調(diào)用partial()函數(shù)然后復(fù)制給part_class,完成于rank對(duì)象的管的關(guān)聯(lián),可以使用同樣的方式來(lái)創(chuàng)建suit對(duì)象,并且完成最終的Card對(duì)象的創(chuàng)建.partial()函數(shù)的使用在函數(shù)時(shí)編程中是很常見(jiàn)的.當(dāng)時(shí)用的是函數(shù)而非對(duì)象方法的時(shí)候就可以考慮使用.

大致上,partial()函數(shù)在面向?qū)ο缶幊讨胁皇呛艹S?我們可以簡(jiǎn)單的的提供構(gòu)造函數(shù)不同版本來(lái)做相同的事情.partial()函數(shù)和構(gòu)造對(duì)象時(shí)的流暢接口很類(lèi)似.

工廠模式的流暢的API設(shè)計(jì)

有時(shí)候我們定義類(lèi)中的方法必須按照特定的順序來(lái)調(diào)用.這種順序調(diào)用的方法和創(chuàng)建 partial() 函數(shù)的方式非常類(lèi)似.

我們可以在流暢接口函數(shù)中設(shè)置可以返回self值的rank對(duì)象,然后傳入花色類(lèi)從而創(chuàng)建Card實(shí)例/

以下是Card工廠流暢接口的定義,包含兩個(gè)函數(shù),他們必須按照順序調(diào)用.

class CardFactory(object):
    def rank(self,rank):
        self.class_,self.rank_str = {
            1:(AceCard,"A"),
            11:(FaceCard,"J"),
            12:(FaceCard,"Q"),
            13:(FaceCard,"K")
        }.get(rank,(NumberCard,str(rank)))
    
    def suit(self,suit):
        return self.class_(self.rank_str,suit)

先使用rank()函數(shù)更新了構(gòu)造函數(shù)的狀態(tài),然后通過(guò)suit()函數(shù)創(chuàng)造了 最終的Card對(duì)象.

def A (rank):

    a,b ={                      # 本身為一個(gè)字典的傳遞值.返回對(duì)應(yīng)的值.是dict的get方法
        1: (AceCard, "A"),
        11: (FaceCard, "J"),
        12: (FaceCard, "Q"),
        13: (FaceCard, "K")
    }.get(rank, (NumberCard, str(rank)))
    return a,b # 返回的是一個(gè)tuple(),a 為  , b 為"3"

a = A(3)
print(a)

我們先實(shí)例化一個(gè)工廠對(duì)象,然然后在創(chuàng)建Card實(shí)例,這用方式?jīng)]有利用__init__() 在Card類(lèi)層級(jí)結(jié)構(gòu)的作用,改變的是調(diào)用者創(chuàng)建創(chuàng)建對(duì)象的方式.

在每個(gè)子類(lèi)中實(shí)現(xiàn)__init__()方法

以下代碼演示了如何把__init__()方法提到基類(lèi)Card中實(shí)現(xiàn)的過(guò)程.然后在子類(lèi)中可以重用基類(lèi)的實(shí)現(xiàn).

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


class NumberCard(Card):
    def __init__(self, rank, suit):
        super().__init__(str(rank), suit, rank, rank)


class AceCard(Card):
    def __init__(self, rank, suit):
        super(AceCard, self).__init__("A", suit, 1, 11)


class FaceCard(Card):
    def __init__(self, rank, suit):
        super(FaceCard, self).__init__({11: "J",
                                        12: "Q",
                                        13: "K"}[rank], suit, 10, 10)
        

def card10(rank,suit):
    if rank == 1:
        return AceCard(rank,suit)
    elif 2<= rank < 11:
        return NumberCard(rank,suit)
    elif 11<= rank <14:
        return FaceCard(rank,suit)
    
    else:
        raise  Exception("Rank out of range")

在這里重構(gòu)了基類(lèi)中的__init__,雖然將它復(fù)雜化,但是這樣的權(quán)衡是正常的.

使用工廠函數(shù)封裝的復(fù)雜性

 在 `__init__()`方法和工廠函數(shù)之間存在一些權(quán)衡,通常直接調(diào)動(dòng)比"程序員友好"的`__init__()`函數(shù)并把復(fù)雜性分發(fā)給工廠函數(shù)更好.當(dāng)需要封裝復(fù)雜的構(gòu)造函數(shù)邏輯時(shí),考慮使用工廠函數(shù)則更好.

簡(jiǎn)單的組合對(duì)象

一個(gè)組合對(duì)象也可以稱(chēng)作容器.

如果業(yè)務(wù)邏輯相對(duì)簡(jiǎn)單,為什么定義新類(lèi)?

類(lèi)的定義的一個(gè)優(yōu)勢(shì)是:

類(lèi)給對(duì)象提供了簡(jiǎn)單的,不需要實(shí)現(xiàn)的接口.

設(shè)計(jì)集合類(lèi),通常是下面三種策略:

封裝:這個(gè)實(shí)際是基于現(xiàn)有集合類(lèi)來(lái)定義一個(gè)新類(lèi),屬于外觀模式的一個(gè)使用場(chǎng)景.

擴(kuò)展:這個(gè)設(shè)計(jì)是對(duì)現(xiàn)有集合類(lèi)進(jìn)行擴(kuò)展,通常使用定義子類(lèi)的方式來(lái)實(shí)現(xiàn).

創(chuàng)建:即重新設(shè)計(jì).

以上是面向?qū)ο笤O(shè)計(jì)的核心.

封裝集合類(lèi)

以下是對(duì)內(nèi)部集合進(jìn)行封裝設(shè)計(jì).

import random
class Deck(object):
   def __init__(self):
       self._cards = [card6(r+1,s) for r in range(13) for s in (Club,Diamond,Heart,Spade)]
       random.shuffle(self._cards)
   def pop(self):
       return self._cards.pop()

d = Deck()

hand = [d.pop(),d.pop()]

一般來(lái)說(shuō)買(mǎi)外觀模式或者封裝類(lèi)中的方法實(shí)現(xiàn)只是對(duì)底層對(duì)象相應(yīng)函數(shù)的代理調(diào)用.

class Desk3(list):
    def __init__(self, decks=1):
       super(Desk3, self).__init__()
       for i in range(decks):
           self.extend(card6(r + 1, s) for r in range(13) for s in (Club, Diamond, Heart, Spade))
           random.shuffle(self)
           burn = random.random(1,52)
           for i in range(burn):
               self.pop()

這里我們使用了基類(lèi)的 __init__()函數(shù)來(lái)創(chuàng)建了一個(gè)空集合,然后調(diào)用了 self.extrend()來(lái)吧多副牌加載到發(fā)牌機(jī)中.

復(fù)雜的組合對(duì)象

模擬打牌策略

class Hand:
    def __init__(self,dealer_card):
        self.dealer_card = dealer_card
        self.cards = []
        
    def hard_total(self):
        return sum(c.hard for c in self.cards)
    
    def soft_total(self):
        return sum(c.soft for c in self.cards)
d = Deck()
h = Hand(d.pop())
h.cards.append(d.pop())
h.cards.append(d.pop())

需要一個(gè)一個(gè)的添加非常不方便

完成組合對(duì)象的初始化

__init__()初始化方法應(yīng)當(dāng)返回一個(gè)完成的對(duì)象,當(dāng)然這個(gè)是理想的情況.而這樣也帶來(lái)復(fù)雜性,因?yàn)橐獎(jiǎng)?chuàng)建的對(duì)象內(nèi)部可能包含了集合,集合里面又包含了其他對(duì)象.

通常考慮使用一個(gè)流暢的接口來(lái)完成逐個(gè)講對(duì)象添加到集合的操作,同時(shí)將集合對(duì)象作為構(gòu)造函數(shù)來(lái)完成初始化.例如:

class Hand2:
    def __init__(self, dealer_card, *cards):
        self.dealer_card = dealer_card
        self.cards = list(cards)

    def hard_total(self):
        return sum(c.hard for c in self.cards)

    def soft_total(self):
        return sum(c.soft for c in self.cards)

d = Deck()
h = Hand2(d.pop(),d.pop(),d.pop(),d.pop())
print(h.cards)
不帶__init__方法的無(wú)狀態(tài)對(duì)象

一個(gè)策略對(duì)象以插件的形式復(fù)合在主對(duì)象上來(lái)完成一種算法或邏輯.它或許以來(lái)主對(duì)象中的數(shù)據(jù),策略對(duì)象自身并不攜帶任何數(shù)據(jù).通常策略類(lèi)會(huì)和亨元設(shè)計(jì)模式一起使用:在策略對(duì)象中避免內(nèi)部存儲(chǔ).所需要的值都從策略對(duì)象方法參數(shù)傳入.策略對(duì)象自身是無(wú)狀態(tài)的.可以把它看做是一系列函數(shù)的集合.

這里定義了一個(gè)類(lèi)給Player實(shí)例提供了游戲的選擇模式,以下這個(gè)策略包括拿牌和下注.

class GameStrategy:
    def insurnace(self, hand):
        return False

    def split(self, hand):
        return False

    def double(self, hand):
        return False

    def hit(self, hand):
        return False

每個(gè)函數(shù)需要傳入已有的Hand對(duì)象,函數(shù)邏輯所需要的數(shù)據(jù)基于現(xiàn)有的可用信息.意味著數(shù)據(jù)來(lái)自于莊家跟玩家的手牌.

一起其他的類(lèi)定義

玩家有兩張策略:打牌和下注.每個(gè)Player實(shí)例回合模擬器進(jìn)行很多次交互.我們這里把這個(gè)模擬器命名為T(mén)able

Table類(lèi)的職責(zé)需要配合Player實(shí)例完成以下事件:

玩家必須要基于玩牌策略初始化一個(gè)牌局.

隨后玩家會(huì)得到一手牌

如果

以下是Table類(lèi)中投注和牌的邏輯處理相關(guān)的代碼

class Table:
    def __init__(self):
        # 生成52張牌
        self.deck = Deck()

    def place_bet(self, amount):
        print("Bet", amount)

    def get_hand(self):
        try:
            # self.hand = Hand2(d.pop(), d.pop(), d.pop())
            # self.hole_card = d.pop() 書(shū)上是這么寫(xiě)的我認(rèn)為不對(duì),改為下面寫(xiě)法
            self.hand = Hand2(self.deck.pop(), self.deck.pop(), self.deck.pop())
            self.hole_card = self.deck.pop()
        except IndexError:
            # Out of cards: need to shuffle
            self.deck = Deck()
            return self.get_hand()
        print("Deal", self.hand)
        return self.hand

    # 沒(méi)有看明白hand從何而來(lái),所以也未找到insure的方法。估計(jì)是寫(xiě)錯(cuò)了。
    def can_insure(self, hand):
        return hand.dealer_card.insure

class BettingStrategy:
    def bet(self):
        raise NotImplementedError("No bet method")
    
    def record_win(self):
        pass
    
    def record_lose(self):
        pass
    
class Flat(BettingStrategy):
    def bet(self):
        return 1

上面的那一段代碼還未看懂需要以后再來(lái)看一遍.

多策略的__init__()方法
class Hand4:
    def __init__(self, *args, **kwargs):
        print(len(args),args,kwargs)
        if len(args) == 1 and isinstance(args[0], Hand4):
            other = args[0]
            self.dealer_card = other.dealer_card
            self.cards = other.cards

        elif len(args) == 2 and isinstance(args[0], Hand4) and "split" in kwargs:
            # Split an existing hand
            other, card = args
            self.dealer_card = other.dealer_card
            self.cards = [other.cards[kwargs["split"]], card]
        elif len(args) == 3:
            # Bulid a fresh ,new hand
            dealer_card,*cards = args
            self.dealer_card = dealer_card
            self.cards = list(cards)

        else:
            raise TypeError("Invaild constructor args= {0!r} kw={1!r}".format(args,kwargs))

    def __str__(self):
        return ",".join(map(str,self.cards))


d = Deck()

h = Hand4(d.pop(),d.pop(),d.pop())
print(h)

# s1 = Hand4(h,d.pop(),split = 0)
# s2 = Hand4(h,d.pop(),split = 1)
class Hand5:
    def __init__(self,dealer_card,*cards):
        self.dealer_card = dealer_card
        self.cards = list(cards)

    @staticmethod
    def freeze(other):
        hand = Hand5(other.dealer_card,*other.cards)
        return hand

    @staticmethod
    def split(other,card0,card1):
        hand0 = Hand5(other.dealer_card,other.cards[0],card0)
        hand1 = Hand5(other.dealer_card,other.cards[1],card1)
        return hand0,hand1

    def __str__(self):
        return ",".join(map(str,self.cards))

d = Deck()

h = Hand5(d.pop(),d.pop(),d.pop())
s1,s2 = Hand5.split(h,d.pop(),d.pop())

上面這段代碼實(shí)現(xiàn)了:當(dāng)?shù)谝惠啺l(fā)完牌是,dealer手牌有一張,Player手牌有兩張,當(dāng)手牌的兩張牌相同的時(shí)候玩家可以選擇分牌,將手中的的兩張牌分為兩組牌,繼續(xù)進(jìn)行游戲.然后發(fā)牌器會(huì)給Palyer每組牌中個(gè)發(fā)一張牌

更多的__init__()技術(shù)

以下是Player類(lèi)的定義,初始化使用兩個(gè)策略對(duì)象和一個(gè)table對(duì)象

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/44466.html

相關(guān)文章

  • 《JavaScript 權(quán)威指南讀書(shū)筆記 1 - 簡(jiǎn)介

    摘要:原文第一章主要介紹的大概情況基本語(yǔ)法。通過(guò)和來(lái)引用對(duì)象屬性或數(shù)組元素的值就構(gòu)成一個(gè)表達(dá)式。 原文:https://keelii.github.io/2016/06/16/javascript-definitive-guide-note-0/ 第一章 主要介紹 JavaScript 的大概情況、基本語(yǔ)法。之前沒(méi)有 JavaScript 基礎(chǔ)的看不懂也沒(méi)關(guān)系,后續(xù)章節(jié)會(huì)有進(jìn)一步的詳細(xì)說(shuō)明...

    sydMobile 評(píng)論0 收藏0
  • 新書(shū)《JavaScript面向對(duì)象編程指南(第2版)》

    摘要:前段時(shí)間在網(wǎng)絡(luò)上看了車(chē)洪才老先生編寫(xiě)阿富汗語(yǔ)詞典的故事。年,萬(wàn)字,完稿時(shí)已斗轉(zhuǎn)星移。然而書(shū)的修成不都如此嗎前有明朝的永樂(lè)大典,近有車(chē)洪才老先生的阿富汗語(yǔ)詞典我還看過(guò)一部電影編舟記,講述的便是一部字典歷經(jīng)十余年的修成。然而我們對(duì)此坦然以待。 我記得去年的這個(gè)時(shí)候我丟了工作,然后每天就是跑步、譯書(shū)、跑步、譯書(shū)。非常單調(diào)的日子過(guò)了兩個(gè)多月。這種日子過(guò)的時(shí)候并沒(méi)有過(guò)多地覺(jué)得什么,但是譯完交稿的...

    silencezwm 評(píng)論0 收藏0
  • 流暢的python讀書(shū)筆記-第一章Python 數(shù)據(jù)模型

    摘要:第一章數(shù)據(jù)類(lèi)型隱式方法利用快速生成類(lèi)方法方法通過(guò)下標(biāo)找元素自動(dòng)支持切片操作可迭代方法與如果是一個(gè)自定義類(lèi)的對(duì)象,那么會(huì)自己去調(diào)用其中由你實(shí)現(xiàn)的方法。若返回,則會(huì)返回否則返回。一個(gè)對(duì)象沒(méi)有函數(shù),解釋器會(huì)用作為替代。 第一章 python數(shù)據(jù)類(lèi)型 1 隱式方法 利用collections.namedtuple 快速生成類(lèi) import collections Card = collec...

    tomener 評(píng)論0 收藏0
  • 流暢的python讀書(shū)筆記-第一章Python 數(shù)據(jù)模型

    摘要:第一章數(shù)據(jù)類(lèi)型隱式方法利用快速生成字典方法方法通過(guò)下標(biāo)找元素自動(dòng)支持切片操作可迭代方法與如果是一個(gè)自定義類(lèi)的對(duì)象,那么會(huì)自己去調(diào)用其中由你實(shí)現(xiàn)的方法。若返回,則會(huì)返回否則返回。一個(gè)對(duì)象沒(méi)有函數(shù),解釋器會(huì)用作為替代。 第一章 python數(shù)據(jù)類(lèi)型 1 隱式方法 利用collections.namedtuple 快速生成字典 import collections Card = coll...

    FullStackDeveloper 評(píng)論0 收藏0
  • 雙十二大前端工程師讀書(shū)清單

    摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書(shū)清單也要收費(fèi)。這本書(shū)便從的異步編程講起,幫助我們?cè)O(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡(jiǎn)單的頁(yè)面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...

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

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

0條評(píng)論

cncoder

|高級(jí)講師

TA的文章

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