【问题标题】:Python: Printing Function To Call a Randomly Generated Class ObjectPython:调用随机生成的类对象的打印函数
【发布时间】:2016-10-18 14:01:20
【问题描述】:

初学者 python 开发人员正在玩并尝试制作纸牌游戏。在我自己的系统上工作以随机选择卡片。

import random

# list to draw random card from from:
card_names = ["ace_h", "two_h", "three_h"]

class Cards(object):

    in_play = False
    def __init__(self, face, color, value):
        self.face = face
        self.color = color
        self.value = value      

ace_h = Cards("Ace", "Hearts", 14)
two_h = Cards("Two", "Hearts", 2)
three_h = Cards("Three", "Hearts", 3)

random_1 = random.choice(card_names)
print (random_1 +".face")

如果假设ace_h 被随机化选中,我希望最后的打印结果会显示打印ace_h.face 的结果(即Ace)。相反,打印只是将ace_h.face 显示为字符串,而不是与其关联的实际值。

我该如何更改?

请注意,只需使用 print (ace_h.face) 即可获得所需的结果。

【问题讨论】:

  • 为什么不先random_1 = random.choice([ace_h, two_h, three_h]) 然后print(random_1.face)
  • 谢谢,这行得通,但我不知道为什么?你的代码和我的代码有什么区别,除了我的指的是预定义的列表?
  • 添加到@elethan:这里甚至不需要命名变量。只需直接在其中制作一个带有卡片的list,因为它们在逻辑上是选项的集合,而不是一堆自变量。
  • @user2390206:elethan 的代码是列出实际对象,而不是描述它们的字符串,并查找实际属性,而不是连接属性名称。
  • @user2390206 正如@ShadowRanger 所说,您的代码只打印字符串,而我的代码在选择Card 时打印face 属性的返回值。如果您 eval() 您的字符串将像 Python 代码一样运行该字符串:print (eval(random_1 +".face")),您可以让您现有的代码以同样的方式工作,但通常不鼓励使用 eval(),因为这涉及潜在的安全风险(尽管由于您没有接受用户输入,因此在这种情况下应该没问题,但在我看来,从对象中随机选择而不是名称是一个更好的选择)。

标签: python-3.x


【解决方案1】:

您对如何在 Python 中引用事物有一个根本性的误解。

在 Python 中你有变量名:

ace_h = 1
two_h = 2
three_h = 3

您可以按名称调用这些值:

print(ace_h)  # => 1

您可以将值放入另一个集合中:

cards = [ace_h, two_h, three_h]
print(cards)  # [1, 2, 3]

您可以打印特定元素:

print(cards[0])

你可以打印一个随机元素:

print(random.choice(cards))

但这些都指的是 1, 2, 3

您实际上可以通过查看id 看到这一点:

print(id(ace_h))
print(id(cards[0]))

不管你是用ace_h还是cards[0]方法来命名值,都是一样的。

这对于 Python 中的 everything 都一样——它们都是对象。您可以给它们起任何类型的名称,无论是变量名称、将它们放在列表中还是字典中 - 只要 id(thing) 相同,您所谈论的对象就是完全相同的。

ace_h = Cards("Ace", "Hearts", 14)
two_h = Cards("Two", "Hearts", 2)
three_h = Cards("Three", "Hearts", 3)

cards = [ace_h, two_h, three_h]

print(cards)
for card in cards:
    print(id(card))

print(id(ace_h))
print(id(two_h))
print(id(three_h))

random_card = random.choice(cards)

print(id(random_card))

print(random_card.face)

print('random card is ace_h? {}'.format(random_card is ace_h))
print('random card is two_h? {}'.format(random_card is two_h))
print('random card is three_h? {}'.format(random_card is three_h))

如果您只是将变量视为附加到值的标签,您会做得更好。在您的情况下,您正在创建 Card 值,并且您将标签 ace_h 贴在上面。您还将Card 放在一个列表中,您可以通过名称cards[0] 引用它。你可以给它任意数量的名字:

another_name = ace_h
cool_name = ace_h
king_arthur = ace_h
sir_lancelot = ace_h
minister_of_silly_walks = ace_h

现在,这些名称中的每一个都指代完全相同的值。你可以用id检查它,你可以看到它们都具有print(dir(ace_h))print(dir(minister_of_silly_walks)))的正确属性。你可以用ace_h is minister_of_silly_walks检查它们是否是同一个对象。

【讨论】:

    【解决方案2】:

    你可以像这样将所有对象放入一个列表中:

    objectList = [ace_h, two_h, three_h]
    random_1 = random.choice(objectList)
    

    然后打印你想要的属性:

    print(random_1.face)

    【讨论】:

      【解决方案3】:

      您可以立即想到几种方法。

      1. 您可以更改您的 MO 并预先初始化变量列表:

        import random
        
        class Cards(object):
            in_play = False
            def __init__(self, face, color, value):
                self.face = face
                self.color = color
                self.value = value      
        
        ace_h = Cards("Ace", "Hearts", 14)
        two_h = Cards("Two", "Hearts", 2)
        three_h = Cards("Three", "Hearts", 3)
        
        # list to draw random card from from:
        cards = [ace_h, two_h, three_h]
        
        random_1 = random.choice(cards)
        print (random_1.face)
        

        如您所见,我只是稍微重新排序了您的代码,以便card_names 可以包含对实际Card 对象的引用而不是它们的名称。这可能是最简单的方法。

      2. 您可以按名称访问全局变量。这有点复杂,可能不是您想要的,但该技术可能对其他事情有用:

        import random
        
        # list to draw random card from from:
        card_names = ["ace_h", "two_h", "three_h"]
        
        class Cards(object):
        
            in_play = False
            def __init__(self, face, color, value):
                self.face = face
                self.color = color
                self.value = value      
        
        ace_h = Cards("Ace", "Hearts", 14)
        two_h = Cards("Two", "Hearts", 2)
        three_h = Cards("Three", "Hearts", 3)
        
        random_1 = random.choice(card_names)
        print(globals()[random_1].face)
        

        这更类似于您的原始代码。 globals() 返回一个 dict 包含在模块级别定义的所有名称,包括函数、类和变量,所有这些名称都以名称为键。因此,globals()[random_1] 将是一个 Cards 对象(顺便说一下,我认为您应该将其重命名为 Card)。

        在函数内部,您可以使用locals() 为该函数中的本地命名空间获取类似的dict()。例如,在Cards.__init__ 中,您可以执行locals()['face'] 之类的操作来访问face 参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-26
        • 1970-01-01
        相关资源
        最近更新 更多