0

昨晚很晚,我问了一个类似但很糟糕的问题(访问实例变量,但不是 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是new_hand_name[0]指实例的变量吗?或者,是hand_3变量?

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

4

1 回答 1

2

首先,回答您的问题:new_hand_name[0]是引用实例的变量 - 更具体地说,它是new_hand_name键 0 访问的字典中的值。new_hand_name如果您打印它,字典将如下所示:

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

将 的值添加"hand_3"到字典中是不必要的,但就此而言,字典也是如此。

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

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())]

这不是更简单吗?

回应您的评论:

  1. 您可以将任何特定手牌称为Players 类self.hands[0]self.hands[1]在 Players 类中。

  2. 如果您想跟踪特定的手,您可以只传递手本身,而不是传递引用该手的字符串。像这样:

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

    这很重要:您在函数中对手的修改对实际手本身起作用。为什么要额外添加一个传递字符串的步骤,然后您必须查找?

    另请注意,特定于每手牌的信息(例如下注)可能应该存储在 Hand 类本身中。

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

    self.hands = {}
    self.hands["hand1"] = Hand([card1, card2])
    self.hands["hand2"] = Hand([card1, card2])
    print self.hands["hand1"]
    

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

于 2012-08-29T21:09:58.517 回答