python中的动态类实例化混淆

时间:2012-08-29 20:47:06

标签: python dynamic instantiation

昨晚很晚(Access to instance variable, but not instance method in Python)我问了一个类似但又糟糕的问题,引起了一些混乱。我会删除它,但我不能。

我现在可以更清楚地问我的问题了。

背景:我正在尝试构建一个黑杰克游戏来学习python语法。每一只手都是Hand类的一个实例,我现在正处于试图让手被分割的位置。因此,当需要分割一只手时,我需要创建两个新的手部实例。鉴于可能进一步拆分,我想重用相同的方法来重新拆分。因此,我(我认为)需要动态实例化Hand类。

以下是我用来阻止机制的代码片段:

import os

os.system("clear")

class Hand():
    instances=[]
    def __init__(self, hand_a, name):
        Hand.instances.append(self)
        self.name = name
        self.hand_a = hand_a

    def show_hand(self):
        ln = len(self.hand_a)
        for x in range(ln):
            print self.hand_a[x]

class Creation():
    def __init__(self):
        pass
    def create_name(self):
        hil = len(Hand.instances)
        new_name = 'hand_' + str(hil + 1)
        return(new_name)

    def new_instance(self):
        new_dict = {0: 'Ace of Clubs', 1: '10 of Diamonds'}
        new_hand_name = {}
        new_hand_name.setdefault(self.create_name(), None)
        print new_hand_name
        new_hand_name[0] = Hand(new_dict, self.create_name())
        print new_hand_name[0]  


hand = Hand("blah", 'hand')
hand_z = Hand("blah_z", 'hand_z')
creation = Creation()
creation.new_instance()

这是输出:

{'hand_3': None}
<__main__.Hand instance at 0x10e0f06c8>

关于由以下声明创建的实例:

new_hand_name[0] = Hand(new_dict, self.create_name)

new_hand_name[0]是否为引用该实例的变量? 或者,变量是hand_3吗?

即。在调用实例方法时,我可以使用hand_3.show_hand()吗?

1 个答案:

答案 0 :(得分:2)

首先,回答你的问题:new_hand_name[0]是引用实例的变量 - 更具体地说,它是由密钥0访问的new_hand_name字典中的值。{{1}字典,如果你打印它,看起来像:

new_hand_name

{'hand_3': None, 0: <__main__.Hand instance at 0x10e0f06c8>} 的值添加到字典中是不必要的,但就此而言,字典也是如此。

想要做的事情与新类的动态实例化无关,这与您的问题无关。问题在于Hand可能代表单个卡片列表,但也可能代表卡片列表的列表,每个卡片都必须单独播放。解决这个问题的一个好方法是在玩家和手牌之间进行分离,并允许玩家拥有多手牌。想象一下这个设计(我也省略了很多二十一点功能,但是稍微留一下,让你知道如何在程序的其余部分中使用它。)

"hand_3"

这不是更简单吗?

回应你的评论:

  1. 您可以在Players课程中将任何特定手牌称为def draw_random_card(): """ whatever function returns a new card. Might be in a Deck object, depends on your design """ # some code here class Player: def __init__(self): self.hands = [] def deal(self): """add a random hand""" self.hands.append(Hand([draw_random_card(), draw_random_card()])) def split(self, hand): """split the given hand""" self.hands.remove(hand) self.hands += hand.split() class Hand: def __init__(self, cards): self.cards = cards def hit(self): """add a random card""" self.cards.append(draw_random_card()) def split(self): """split and return a pair of Hand objects""" return [Hand(self.cards[0], draw_random_card()), Hand(self.cards[1], draw_random_card())] self.hands[0]

  2. 如果你想跟踪一只特定的牌,你可以直接传球,而不是传递一只指向该牌的角色。像这样:

    self.hands[1]

    这一点非常重要:您在功能中对手进行的修改适用于实际手本身。为什么要传递一个字符串的额外步骤,然后你必须查找它?

    另请注意,每只手的特定信息(例如投注)应该存储在Hand类本身中。

  3. 如果您确定要使用特定名称引用每只手(并且在这种情况下也没有必要),您只需使用带有这些名称的字典作为键:

    def process_hand(hand):
        """do something to a hand of cards"""
        h.hit()
        print h.cards()
        h.hit()
    h = Hand(cards)
    process_hand(h)
    

    但同样,也许没有充分理由这样做。 (请注意,这与“动态”实例化新变量非常不同。查看字典的工作原理是个好主意。