返回单个卷的Python骰子类

时间:2018-01-21 19:43:25

标签: python list class return subclass

我试图使用DiceShaker()子类创建一个Die()类。 DiceShaker()子类应该采用Die()类的多个副本,滚动它们,然后返回各个卷。这是我的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()应返回一个列表,其中包含通过shake()传递的所有骰子,但打印的列表始终只是一个数字。 示例:

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

我摇晃()返回[none]只是因为我知道正确数量的骰子正在经历,但我无法弄清楚为什么getIndividualRolls()会继续打印出重复数据。任何人都可以帮我弄清楚我做错了什么吗?

2 个答案:

答案 0 :(得分:1)

这对于评论来说太长了:

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

为什么您的DiceShakerDie的子类?这毫无意义。子类化用于is a关系。 DiceShaker不是Die的类型(就像ShoppingCart不是CartItem的类型)。你的关系是有组织的。 DiceShakerDie个(您用dieList反映)。在这种情况下,dieList就是您所需要的。您无需继承Die

您获得相同数字的根本原因是因为您从die继承。通过继承Die,您使DiceShaker的行为类似于Die。这意味着您可以调用ds.roll()ds.get()(其中ds = DiceShaker()),它的行为与您在Die上调用它的行为完全相同。这实际上就是你在写Dice.get(self)时所做的。这相当于self.get()(因为DiceShaker扩展了Dice)。但是DiceShaker只有一个Die,而不是多个。因此,调用get()将始终返回相同的内容。你有效地完成了以下工作:

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),我们在每个get_value_rolled上调用Die.get(相当于您的Die)我们的振动器包含的内容(在列表self.dice)。

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

  • Python中的惯例是将snake_case用于变量/属性和函数
  • 我重命名了一些功能,以使他们的关系更加清晰(get_value_rolledget_values_rolled
  • 我使用list comprehensions(例如[Die(num_die_sides) for _ in range(num_die)]append self.dieList对你的while的while循环相同,但更为pythonic)
  • 我将for替换为for。通常在python中,当你使用iterables(list list)时,你想使用DieShaker
  • 我删除了__init__构造函数的一些可选参数。为了你的目的,允许它们被传入是没有多大意义的(如果你想涉及更多的技术,你有理由这样做,但为了你的目的,不要) 。您可能认为自己需要将所有内容作为def __init__(self, num_die=1, die_sides=6, dice = []): self.dice = dice 的参数,但事实并非如此。而不是这个(实际上是has a serious issue unrelated to the style/semantics):

为:

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

你可能应该这样做:

roll()
  • 我删除了你的第二个清单。你只需要维护一个die的列表(因为在每个die上调用get_value()之后,每次都会为schemas返回相同的东西)

答案 1 :(得分:0)

您的DieShaker类应该只是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]