Python 骰子 class returns 个人掷骰子

Python dice class that returns individual rolls

我正在尝试使用 DiceShaker() subclass 制作 Die() class。 DiceShaker() subclass 应该获取 Die() class 的多个副本,滚动它们,然后 return 单独滚动。这是我的 Die() 代码。

class Die(object):
 'a class representing a Die'
  def __init__(self, sides=6):
     'initialize a die, default 6 sides'
      self.sides = sides

 def roll(self):
     'roll the dice'
      self.dieRoll = random.randint(1, self.sides)


 def get(self):
     'get the current value of the die'
      return self.dieRoll

这是我的 DiceShaker() 代码。

class DiceShaker(Die):
'DiceShaker class'

def __init__(self,dieCount=1, dieSides=6, dieList = [], dieList2 = []):
    'initialize a dice shaker'
    Die.__init__(self,sides = 6) 
    self.dieCount = dieCount
    self.dieSides = dieSides
    self.dieList = dieList
    self.dieList2 = dieList2


def shake(self):
    'shake all the dice in the shaker'
    counter = 0
    dieList = [] 
    while counter != self.dieCount:
        self.dieList.append(Die.roll(self)) 
        counter = counter + 1
    return self.dieList 

def getIndividualRolls(self):
    'get a lsit of integers of all the individual die rolls'
    for items in self.dieList:
        self.dieList2.append(Die.get(self))
    return self.dieList2

getIndividualRolls() 应该 return 一个列表,其中包含通过 shake() 传递的所有骰子,但打印的列表始终只有一个数字。 示例:

d=DiceShaker(3)
d.shake()
[None, None, None]
d.getIndividualRolls()
[3, 3, 3]

我有 shake() returning [none] 只是为了我知道正确的骰子数量正在经历,但我不明白为什么 getIndividualRolls() 保持打印出副本。谁能帮我弄清楚我做错了什么?

您的 DieShaker class 应该只是 Die 对象列表的包装器。

class Die(object):
    'a class representing a Die'
    def __init__(self, sides=6):
        'initialize a die, default 6 sides'
        self.sides = sides
        # You should make sure that by the time someone has created a Die object, 
        # all the attributes they might want to access have been defined
        self.roll()

   def roll(self):
       'roll the dice'
        self.dieRoll = random.randint(1, self.sides)

   # Note I got rid of Die.get 
   # Anyone who can call Die.get can see Die.dieRoll

class DiceShaker(object):
    def __init__(self, dice=()): # Note we avoid mutable default arguments
        self.dice = list(dice)   # Presumably it would be nice to add/remove dice

    def shake(self):
        for die in self.dice:
            die.roll()
        # return self.get_dice() 
        # It doesn't really make sense for this to return anything

    def get_dice(self):
        return [die.dieRoll for die in self.dice]

评论太长了:

顺便说一句,你真的应该学习 Python 3。Python 2 是 on the way out。以下所有内容均适用于 Python 3.

为什么您的 DiceShakerDie 的子类?这是没有意义的。子类化用于 is a 关系。 DiceShaker 不是 Die 的一种(就像 ShoppingCart 不是 CartItem 的一种)。你们的关系是组合的。 DiceShakerDies(您用 dieList 反映)。在这种情况下,dieList 就是您所需要的。您不需要从 Die.

继承

你得到相同数字的根本原因是因为你继承了死亡。通过子类化 Die,您使 DiceShaker 表现得像 Die。这意味着您可以调用 ds.roll()ds.get()(其中 ds = DiceShaker()),它的行为与您在 Die 上调用它的行为完全相同。这实际上就是您在编写 Dice.get(self) 时所做的。这相当于 self.get()(因为 DiceShaker 扩展了 Dice)。但是DiceShaker只是一个Die,不是多个。所以调用 get() 总是会 return 同样的事情。您有效完成的如下:

die = Die()
die.roll()

for other_die in self.dieList:
    self.dieList2.append(die.get())  # note you're getting the same die each time

所以要解决这个问题,您不需要继承 Die。事实上你不应该。而是组成 DieShakerDie。这意味着 DieShaker 应该委托给它包含的 Die(通过对它们调用 get 而不是它自己 )。

from random import randint

class Die:
    def __init__(self, sides=6):
        self.sides = sides

    def roll(self):
        self._rolled_value = randint(1, self.sides)

    def get_value_rolled(self):
        return self._rolled_value


class DieShaker:
    def __init__(self, num_die=1, num_die_sides=6):
        self.dice = [Die(num_die_sides) for _ in range(num_die)]

    def shake(self):
        for die in self.dice:
            die.roll()

    def get_values_rolled(self):
        return [die.get_value_rolled() for die in self.dice]

请注意,在 get_values_rolled(相当于您的 DieShaker.getIndividualRolls)中,我们如何在每个 Die 上调用 get_value_rolled(相当于您的 Die.get)摇床包含(在列表self.dice)。

另请注意,我通过以下方式清理了您的代码:

  • Python 中的惯例是将 snake_case 用于 variables/properties 和函数
  • 我重命名了一些函数以使它们的关系更清楚(get_value_rolledget_values_rolled
  • 我使用了 list comprehensions(例如 [Die(num_die_sides) for _ in range(num_die)] 与你的 while 循环相同,appends 到你的 self.dieList,但更 pythonic)
  • 我用 for 替换了 while。通常在 python 中,当您使用可迭代对象(列表 list)时,您希望使用 for
  • 我删除了 DieShaker 构造函数的一些可选参数。出于您的目的,允许传入它们没有多大意义(如果您想涉足更多技术,那么您这样做是有原因的,但为了您现在的目的,请不要这样做) .看起来您可能认为您需要将所有内容都作为 __init__ 的参数,但您不需要。而不是这个(实际上 has a serious issue unrelated to the style/semantics):

差:

def __init__(self, num_die=1, die_sides=6, dice = []):
    self.dice = dice

您可能应该这样做:

def __init__(self, num_die=1, die_sides=6):
    self.dice = []
  • 我删除了你的第二个列表。你只需要维护一个骰子列表(因为在每个骰子上调用 roll() 之后,它会 return 每次 get_value() 相同的事情)