在Python中如何通过for循环创建具有随机属性值的对象?

3

你好,我在通过循环创建对象时无法使属性的值每次随机。我想要实现的目标是每次实例化一个对象时,每个对象的self.hunger和self.boredom都具有从0到20不同的值,但每次通过for循环打印critters字典时,它们的self.hunger和self.boredom是相同的。如何使其随机?并且你能解释一下为什么我的代码没有成功吗?这里是我的部分代码,请帮忙看一下。感谢任何答案。

class Critter(object):
    """A virtual pet"""
    import random

    def __init__(self, name, hunger = random.randrange(0, 21), boredom = random.randrange(0, 21)):
        self.name = name
        self.hunger = hunger
        self.boredom = boredom

    def __str__(self):
        rep = "\nCritter object\n"
        rep += "Name: " + str(self.name) + ", Hunger: " + str(self.hunger) + ", Boredom: " + str(self.boredom)
        return rep 

def main():
    critters = {}
    crit_name = input("What do you want to name to your critter?: ")
    critters[1] = Critter(crit_name)
    choice = None
    while choice != "0":
        print \
        ("""
        Critter Caretaker

        0 - Quit
        1 - Listen to your critters
        2 - Feed your critters
        3 - Play with your critters
        4 - Create another critter
        """)

elif choice == "4":
            crit_name = input("What do you want to name your critter?: ")
            for i in range(len(critters) + 1, 11):
                critters[i] = Critter(crit_name)
                break
            if i == 10:
                print("\nMaximum critters reached. Cannot create another critter.")

如果你希望整个程序能够理解我的问题,我会编辑我的问题。请帮助我。


使默认参数=None,并在构造函数中运行arg=def_value if arg is None else arg - Serge Seredenko
3个回答

4
这是因为您将随机值作为默认参数传递,并且它们仅被评估一次。尝试使用以下方式:
import random

class Critter(object):
    """A virtual pet"""

    def __init__(self, name, hunger=None, boredom=None):
        self.name = name
        self.hunger = hunger if hunger is not None else random.randrange(0, 21)
        self.boredom = boredom if boredom is not None else random.randrange(0, 21)

    def __str__(self):
        rep = "\nCritter object\n"
        rep += "Name: " + str(self.name) + ", Hunger: " + str(self.hunger) + ", Boredom: " + str(self.boredom)
        return rep 

好的,您好。感谢您的回答。但是说实话,我不熟悉“hunger if hunger is not None else random.randrange(0, 21)”,您能解释一下这个是什么意思吗? - John Cruz
1
这是Python中的if-else简写(一行中的if else,但你也可以只使用普通的if else:这样你就可以写更少的代码。它的作用很简单:如果饥饿是None(没有传递值),则生成一个随机值;如果传递了一个值(不同于None),则使用该值。 - Daniele Pantaleone

1

默认参数值总是在其所属的“def”语句被执行时评估,而且仅在此时评估。

因此,在函数(或方法)的默认参数被评估之前只会发生一次。如果您想要不同的随机值,请在初始化器中分配默认值。

class Critter(object):
"""A virtual pet"""
      import random

    def __init__(self, name, hunger = None, boredom = None):
        self.name = name
        self.hunger = random.randrange(0, 21) if hunger is None else hunger
        self.boredom = random.randrange(0, 21) if boredom is None else boredom

只会被评估一次。尽管如果None是由@jonrsharpe指出作为参数传递的有效值,则需要不同的解决方案。

class Nil(object):
     pass

nil = Nil()

class Critter(object):
"""A virtual pet"""
      import random

    def __init__(self, name, hunger = nil, boredom = nil):
        self.name = name
        self.hunger = random.randrange(0, 21) if hunger is nil else hunger
        self.boredom = random.randrange(0, 21) if boredom is nil else boredom

2
仔细考虑一下,如果你想创建一个不饥饿的生物,该怎么办? - jonrsharpe
实际上,在这种情况下使用 hunger or random.randrange(0, 21) 是不正确的,因为饥饿度和无聊度都应该是整数。如果我将hunger=0作为参数传递,则会生成随机数,即使我已经指定了一个值,因为0会被评估为False。 - Daniele Pantaleone
@jonrsharpe 感谢您指出这一点,我已经修改了我的答案。我猜这个可能会起作用。 - hspandher
你误解了我的观点;None作为有效输入是没有意义的,0是有意义的。现在这个问题变得非常复杂了,只需要通过身份测试None而不是真实性即可。 - jonrsharpe

0
如果你想要能够设置hungerboredom,但也允许它默认为某些随机值:
def __init__(self, name, hunger = None, boredom = None):
    self.name = name
    self.hunger = hunger if hunger is not None else random.randrange(0, 21)
    self.boredom = boredom if boredom is not None else random.randrange(0, 21)

你所拥有的,就像xkcd中所说的一样:

def get_random_number():
    return 4  # chosen by a fair dice roll.
              # guaranteed to be random.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接