面对对象编程估计我们最早接触到的就是__init__了,也就是实例的初始化处理过程:
1:来看看最基础的__init__
1 class Card(object): #抽象类Card,并不用于实例化 2 def __init__( self, rank, suit ): 3 self.suit= suit 4 self.rank= rank 5 self.hard, self.soft = self._points() 6 print("try") 7 8 class NumberCard( Card ): 9 def _points( self ): 10 return int(self.rank), int(self.rank) 11 12 class AceCard( Card ): 13 def _points( self ): 14 return 1, 11 15 16 class FaceCard( Card ): 17 18 def _points( self ): 19 return 10, 10 20 21 22 cards = [ AceCard('A', 'spade'), NumberCard('2','clube'), NumberCard('3','diamond'),]
#注意此地,若子类没有写__init__方法,那么在实例化时会完整的继承实现一遍父类的__init__,所以这里会打印出三个'try'
2:在子类中使用__init__
在子类中写__init__方法的目的要么是实际传入参数(此地),要么是添加其他属性或者操作,都可以通过super()来获得父类__init__方法。否则不用写就会自动继承执行父类的__init__方法
1 class Card: 2 def __init__( self, rank, suit, hard, soft ): 3 self.rank= rank 4 self.suit= suit 5 self.hard= hard 6 self.soft= soft 7 8 class NumberCard( Card ): 9 def __init__( self, rank, suit ): 10 super().__init__( str(rank), suit, rank, rank ) #在子类中使用super().__init__(*args)要传入除了self外所有参数 11 12 class AceCard( Card ): 13 def __init__( self, rank, suit ): 14 super().__init__( "A", suit, 1, 11 ) 15 16 class FaceCard( Card ): 17 def __init__( self, rank, suit ): 18 super().__init__( {11: 'J', 12: 'Q', 13: 'K' }[rank], suit,10, 10 )
3:没有__init__方法:
完全没有__init__方法的类经常是作为策略类使用,策略类就是把一些列相关操作集合起来的类,通过方法传入的参数来进行一些列操作
例如下面的游戏操作策略类,通过传入手牌这一参数决定了每一方法的使用。
1 class GameStrategy: 2 def insurance( self, hand ): #hand是手牌 3 return False 4 def split( self, hand ): 5 return False 6 def double( self, hand ): 7 return False 8 def hit( self, hand ): 9 return sum(c.hard for c in hand.cards) <= 17
4:若init方法太繁琐,有时用 静态方法 生成并且返回实例会更清晰简洁
这里模拟了庄家发牌的过程,庄家手上先拿到n张牌(n个人),然后通过静态方法split(分发)出去
1 class Hand5: 2 def __init__( self, dealer_card, *cards ): 3 self.dealer_card= dealer_card 4 self.cards = list(cards) 5 6 @staticmethod 7 def freeze( other ): #冻结手牌 8 hand= Hand5( other.dealer_card, *other.cards ) 9 return hand 10 11 @staticmethod 12 def split( other, card0, card1 ): 13 hand0= Hand5( other.dealer_card, other.cards[0], card0 ) 14 hand1= Hand5( other.dealer_card, other.cards[1], card1 ) 15 return hand0, hand1 16 17 def __str__( self ): 18 return ", ".join( map(str, self.cards) ) 19 20 d = Deck() 21 h = Hand5( d.pop(), d.pop(), d.pop() ) 22 s1, s2 = Hand5.split( h, d.pop(), d.pop() )
5:另一种初始化属性的方法:
#常用情况:
1 class Player: 2 def __init__( self, table, bet_strategy, game_strategy ): 3 self.bet_strategy = bet_strategy 4 self.game_strategy = game_strategy 5 self.table= table 6 7 #也可以写成这样 8 class Player2: 9 def __init__( self, **kw ): 10 """Must provide table, bet_strategy, game_strategy.""" 11 self.__dict__.update( kw ) #__dict__见下,dict.update(name='pd',...)可添加键值对
P = Player2(table = table,bet_strategy = bet_strategy, game_strategy = game_strategy) #注意实例化的参数形式 12 13 14 #上面方法虽然扩展性好,但是implicit。适合用于做基类,在此基础上可以明确声明一部分初始化参数 15 class Player3( Player ): 16 def __init__( self, table, bet_strategy, game_strategy, **extras): 17 self.bet_strategy = bet_strategy 18 self.game_strategy = game_strategy 19 self.table= table 20 self.__dict__.update( extras )
1 >>> class aha(object): 2 ... def __init__(self,name,age): 3 ... self.name = name 4 ... self.age = age 5 ... 6 >>> aha.__dict__ 7 dict_proxy({'__dict__': <attribute '__dict__' of 'aha' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'aha' objects>, '__doc__': None, '__init__': <function __init__ at 0x0000000002C35908>}) 8 >>> a=aha('pd',12) 9 >>> a.__dict__ 10 {'age': 12, 'name': 'pd'}
6:带检验初始化
1 class ValidPlayer: 2 def __init__( self, table, bet_strategy, game_strategy ): 3 assert isinstance( table, Table ) #assert遇错误会报错并且中断程序 4 assert isinstance( bet_strategy, BettingStrategy ) 5 assert isinstance( game_strategy, GameStrategy ) 6 self.bet_strategy = bet_strategy 7 self.game_strategy = game_strategy 8 self.table= table 9 10 #但这违背了python动态语言的特性,在用python时我们希望能够动态传入,但是应该写doc给programmer提醒,并且若有人没有按动态传入,可log后再分析 11 12 class ValidPlayer: 13 """ 14 Creates a new player associated with a table,and configured with proper betting and play strategies 15 :param table: an instance of :class:`Table` 16 :param bet_strategy: an instance of :class:`BettingStrategy` 17 :param game_strategy: an instance of :class:`GameStrategy` 18 通过 ValidPlayer.__doc__ 访问这段话 19 """ 20 def __init__( self, table, bet_strategy, game_strategy ): 21 assert isinstance( table, Table ) #assert遇错误会报错中断 22 assert isinstance( bet_strategy, BettingStrategy ) 23 assert isinstance( game_strategy, GameStrategy ) 24 self.bet_strategy = bet_strategy 25 self.game_strategy = game_strategy 26 self.table= table