Pythonオブジェクト向けプログラミングガイド読書ノート
第一部は特殊な方法でPythonスタイルのクラスを実現する
より良い拡張性を実現するために、Python言語は多くの特殊な方法を提供しており、大きく以下のいくつかの種類に分けられています.プロパティアクセス 呼び出し可能オブジェクト 集合 数字 コンテキスト 反復器 第一章使用_init()__方法
Python中所有的事物都対象!!!!!!_init__()メソッドは2点を覚えます. __init()__(初期化)はオブジェクトのライフサイクルの開始であり、各オブジェクトが正しく初期化されなければ正常に動作しません. __init__()は、 を割り当てることができる
オブジェクトのライフサイクルは、主に作成、初期化、破棄されます.'暗黙的ではなく表示:各_についてinit__()メソッドは、初期化する変数を設定して表示する必要があります.オブジェクトを作成するたびにpythonは空のオブジェクトを作成し、そのオブジェクトの_を呼び出します.init__()関数は、初期化された操作を提供します.
ファクトリ関数で呼び出す_init__():
このコードは52枚のカードオブジェクトの作成を完了した.
マッピングとクラスを使用して設計を簡略化する.
クラスは第1レベルのオブジェクトであるためrankパラメータからオブジェクトに射出することは容易である.次のカード類工場はマッピングを用いて実現されたバージョンである.
マッピングロジックを修正する必要があり、Cardサブクラスを提供するほか、rankオブジェクトの文字列結果を提供する必要がある.この2つの部分のマッピングをどのように実現するかには、4つの一般的なスキームがある.は、2つの並列マッピング を確立することができる.は、1つの二元グループにマッピングすることができる. はpartial()関数としてマッピングすることができる. は、クラス定義を修正する完了マッピングロジック.1を考慮することができる.パラレルマッピング
これは行う価値がなく、マッピングキー1,11,12,13の論理的重複をもたらす.
パラレル構造を使用しないでください.パラレル構造は元祖またはより良い組み合わせに置き換えられるべきです.は、1つの額面値のタプル にマッピングされる.
rank値からクラスオブジェクトにマッピングする場合は珍しく、2つのパラメータはオブジェクトの初期化に1つしかない.rankから比較的簡単なクラスや関数オブジェクトにマッピングする、目的の不明確なパラメータを提供する必要がないのが賢明な選択である.
3.partial関数設計
partial()関数を呼び出してpart_にコピーclassは、rankオブジェクトのチューブの関連付けを完了する、同様の方法でsuitオブジェクトを作成し、最終的なCardオブジェクトの作成を完了することができる.partial()関数の使用は関数時のプログラミングにおいてよく見られる.その際,オブジェクトではなく関数を用いる方法が考えられる.
大体、partial()関数はオブジェクト向けのプログラミングではあまりよく使われていないので、構造関数の異なるバージョンを簡単に提供して同じことをすることができます.partial()関数はオブジェクトを構築する際のスムーズなインタフェースと似ている.ファクトリモードのスムーズなAPI設計は、クラス内のメソッドを特定の順序で呼び出す必要がある場合がある.この順序呼び出しの方法はpartial()関数を作成する方法と非常に似ている.
スムーズインタフェース関数でself値を返すrankオブジェクトを設定し、花色クラスに転送してCardインスタンス/
以下はCardファクトリのスムーズなインタフェースの定義であり、2つの関数を含み、順序に従って呼び出さなければならない.
まずrank()関数を用いてコンストラクション関数の状態を更新し、suit()関数によって最終的なCardオブジェクトを作成する.
まずファクトリオブジェクトをインスタンス化し、次にCardインスタンスを作成します.これは使用されません.init__()Cardクラスの階層構造の役割は、呼び出し者がオブジェクトを作成する方法を変更する.
各サブクラスで実装__init__()メソッド
次のコードは、__をどのように表示するかを示しています.init__()方法はベースクラスカードで実現する過程に言及する.次に、サブクラスでベースクラスの実装を再利用することができる.
ここではベースクラスの
ファクトリ関数パッケージの使用の複雑さ
単純なコンビネーションオブジェクト
1つの組み合わせの対象を容器と呼ぶこともできる.
ビジネスロジックが比較的単純な場合、なぜ新しいクラスを定義しますか?
クラスの定義の利点の1つは、次のとおりです.クラスはオブジェクトに簡単な、実現する必要のないインタフェースを提供する.
集合クラスを設計します.通常、次の3つのポリシーがあります.パッケージ:これは実際には既存の集合クラスに基づいて新しいクラスを定義し、外観モードの使用シーンに属する. 拡張:この設計は既存の集合クラスを拡張するものであり、通常はサブクラスを定義する方式で実現される. 作成:再設計.
以上が対象設計の核心である.
パッケージ集合クラス
以下、内部集合のパッケージ設計を行う.
一般に、外観モードまたはパッケージクラスを購入する方法は、下位オブジェクトに対応する関数のエージェント呼び出しにすぎない.
ここでは、ベースクラスの
複雑なコンビネーションオブジェクト
トランプ戦略をシミュレートする
1つずつ追加するのは大変不便です
コンビネーションオブジェクトの初期化を完了
一般に、スムーズなインタフェースを用いて、集合にオブジェクトを追加する操作を完了するとともに、集合オブジェクトを構造関数として初期化を完了することが考えられる.例:
1つのポリシーオブジェクトはプラグインの形式で主オブジェクトに複合してアルゴリズムまたは論理を完成する.これは、プライマリオブジェクト内のデータである可能性があり、ポリシーオブジェクト自体はデータを携帯していない.通常、ポリシークラスはヘンメタ設計モードとともに使用する:ポリシーオブジェクトに内部記憶を避ける.必要な値はすべてポリシーオブジェクトのメソッドパラメータから入力.ポリシーオブジェクト自体は無状態である.一連の関数の集合と見なすことができる.
ここでは、Playerのインスタンスにゲームを提供するクラスの選択モードを定義し、以下のポリシーには、トランプと注釈が含まれる.
各関数は既存のHandオブジェクトに伝達する必要があり、関数論理に必要なデータは既存の利用可能な情報に基づいている.データは荘家とプレイヤーの手札から来ていることを意味する.
その他のクラス定義
プレイヤーにはトランプと賭けの2つの戦略がある.各Playerインスタンスのラウンドシミュレータは、複数回のインタラクションを行う.ここではこのシミュレータをTableと名付けます
Tableクラスの役割は、Playerインスタンスに合わせて次のイベントを完了する必要があります.プレイヤーは、トランプ戦略に基づいてトランプを初期化しなければならない. その後プレイヤーは手札 を手に入れる 以下にTableクラスにおける賭けとカードの論理処理に関するコードを示す.
上のコードがまだ読めていないので、後でもう一度見に来なければなりません.
マルチポリシーの
第1ラウンドが終了すると、dealerの手札が1枚、Playerの手札が2枚あり、手札の2枚が同じ場合、プレイヤーは分札を選択し、手の中の2枚を2組に分けてゲームを継続することができる.そしてトランプはPalyerの各グループに1枚のカードを送ります
より多くの
以下はPlayerクラスの定義です.初期化には2つのポリシーオブジェクトと1つのtableオブジェクトを使用します.
略
より良い拡張性を実現するために、Python言語は多くの特殊な方法を提供しており、大きく以下のいくつかの種類に分けられています.
Python中所有的事物都対象!!!!!!_init__()メソッドは2点を覚えます.
オブジェクトのライフサイクルは、主に作成、初期化、破棄されます.'暗黙的ではなく表示:各_についてinit__()メソッドは、初期化する変数を設定して表示する必要があります.オブジェクトを作成するたびにpythonは空のオブジェクトを作成し、そのオブジェクトの_を呼び出します.init__()関数は、初期化された操作を提供します.
# 21 。
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','♠')
ファクトリ関数で呼び出す_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")
rank suit card .
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枚のカードオブジェクトの作成を完了した.
マッピングとクラスを使用して設計を簡略化する.
クラスは第1レベルのオブジェクトであるためrankパラメータからオブジェクトに射出することは容易である.次のカード類工場はマッピングを用いて実現されたバージョンである.
def card4(rank,suit):
class_ = {1:AceCard,11:FaceCard,12:FaceCard,13:FaceCard}.get(rank,NumberCard)
return class_(rank,suit)
マッピングロジックを修正する必要があり、Cardサブクラスを提供するほか、rankオブジェクトの文字列結果を提供する必要がある.この2つの部分のマッピングをどのように実現するかには、4つの一般的なスキームがある.
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)
これは行う価値がなく、マッピングキー1,11,12,13の論理的重複をもたらす.
パラレル構造を使用しないでください.パラレル構造は元祖またはより良い組み合わせに置き換えられるべきです.
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値からクラスオブジェクトにマッピングする場合は珍しく、2つのパラメータはオブジェクトの初期化に1つしかない.rankから比較的簡単なクラスや関数オブジェクトにマッピングする、目的の不明確なパラメータを提供する必要がないのが賢明な選択である.
3.partial関数設計
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)
partial()関数を呼び出してpart_にコピーclassは、rankオブジェクトのチューブの関連付けを完了する、同様の方法でsuitオブジェクトを作成し、最終的なCardオブジェクトの作成を完了することができる.partial()関数の使用は関数時のプログラミングにおいてよく見られる.その際,オブジェクトではなく関数を用いる方法が考えられる.
大体、partial()関数はオブジェクト向けのプログラミングではあまりよく使われていないので、構造関数の異なるバージョンを簡単に提供して同じことをすることができます.partial()関数はオブジェクトを構築する際のスムーズなインタフェースと似ている.
スムーズインタフェース関数でself値を返すrankオブジェクトを設定し、花色クラスに転送してCardインスタンス/
以下はCardファクトリのスムーズなインタフェースの定義であり、2つの関数を含み、順序に従って呼び出さなければならない.
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()関数を用いてコンストラクション関数の状態を更新し、suit()関数によって最終的なCardオブジェクトを作成する.
def A (rank):
a,b ={ # . . dict get
1: (AceCard, 'A'),
11: (FaceCard, 'J'),
12: (FaceCard, 'Q'),
13: (FaceCard, 'K')
}.get(rank, (NumberCard, str(rank)))
return a,b # tuple(),a , b '3'
a = A(3)
print(a)
まずファクトリオブジェクトをインスタンス化し、次にCardインスタンスを作成します.これは使用されません.init__()Cardクラスの階層構造の役割は、呼び出し者がオブジェクトを作成する方法を変更する.
各サブクラスで実装__init__()メソッド
次のコードは、__をどのように表示するかを示しています.init__()方法はベースクラスカードで実現する過程に言及する.次に、サブクラスでベースクラスの実装を再利用することができる.
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')
ここではベースクラスの
__init__
を再構成する、それを複雑化するが、このようなトレードオフは正常である.ファクトリ関数パッケージの使用の複雑さ
`__init__()` , ' ' `__init__()` . , .
単純なコンビネーションオブジェクト
1つの組み合わせの対象を容器と呼ぶこともできる.
ビジネスロジックが比較的単純な場合、なぜ新しいクラスを定義しますか?
クラスの定義の利点の1つは、次のとおりです.
集合クラスを設計します.通常、次の3つのポリシーがあります.
以上が対象設計の核心である.
パッケージ集合クラス
以下、内部集合のパッケージ設計を行う.
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()]
一般に、外観モードまたはパッケージクラスを購入する方法は、下位オブジェクトに対応する関数のエージェント呼び出しにすぎない.
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()
ここでは、ベースクラスの
__init__()
関数を用いて空の集合を作成し、self.extrend()
を呼び出して複数のサブカードを発札機にロードする.複雑なコンビネーションオブジェクト
トランプ戦略をシミュレートする
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())
1つずつ追加するのは大変不便です
コンビネーションオブジェクトの初期化を完了
__init__()
の初期化方法は、もちろんこれが理想的な場合である完了したオブジェクトを返すべきである.これは、作成するオブジェクトの内部に集合が含まれている可能性があり、集合には他のオブジェクトが含まれているため、複雑さをもたらす.一般に、スムーズなインタフェースを用いて、集合にオブジェクトを追加する操作を完了するとともに、集合オブジェクトを構造関数として初期化を完了することが考えられる.例:
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__
メソッドを持たないステータスレスオブジェクト1つのポリシーオブジェクトはプラグインの形式で主オブジェクトに複合してアルゴリズムまたは論理を完成する.これは、プライマリオブジェクト内のデータである可能性があり、ポリシーオブジェクト自体はデータを携帯していない.通常、ポリシークラスはヘンメタ設計モードとともに使用する:ポリシーオブジェクトに内部記憶を避ける.必要な値はすべてポリシーオブジェクトのメソッドパラメータから入力.ポリシーオブジェクト自体は無状態である.一連の関数の集合と見なすことができる.
ここでは、Playerのインスタンスにゲームを提供するクラスの選択モードを定義し、以下のポリシーには、トランプと注釈が含まれる.
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
各関数は既存のHandオブジェクトに伝達する必要があり、関数論理に必要なデータは既存の利用可能な情報に基づいている.データは荘家とプレイヤーの手札から来ていることを意味する.
その他のクラス定義
プレイヤーにはトランプと賭けの2つの戦略がある.各Playerインスタンスのラウンドシミュレータは、複数回のインタラクションを行う.ここではこのシミュレータをTableと名付けます
Tableクラスの役割は、Playerインスタンスに合わせて次のイベントを完了する必要があります.
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() ,
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
# hand , insure 。 。
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
上のコードがまだ読めていないので、後でもう一度見に来なければなりません.
マルチポリシーの
__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())
第1ラウンドが終了すると、dealerの手札が1枚、Playerの手札が2枚あり、手札の2枚が同じ場合、プレイヤーは分札を選択し、手の中の2枚を2組に分けてゲームを継続することができる.そしてトランプはPalyerの各グループに1枚のカードを送ります
より多くの
__init__()
テクノロジー以下はPlayerクラスの定義です.初期化には2つのポリシーオブジェクトと1つのtableオブジェクトを使用します.
略