这是我到目前为止所做的:
class Die (object):
def __init__(self,sides):
self.sides = sides
def roll(self):
return random.randint(1,self.sides)
def __add__(self,other):
return Dice(self,other)
def __unicode__(self):
return "1d%d" % (self.sides)
def __str__(self):
return unicode(self).encode('utf-8')
class Dice (object):
def __init__(self, num_dice, sides):
self.die_list = [Die(sides)]*num_dice
def __init__(self, *dice):
self.die_list = dice
def roll(self):
return reduce(lambda x, y: x.roll() + y.roll(), self.die_list)
但是,当我尝试执行Dice(3,6)
并随后调用roll
操作时,它说它不能,因为'int' object has no attribute 'roll'
。这意味着它首先进入varargs构造函数。我可以做些什么来完成这项工作,还是有另一种选择?
答案 0 :(得分:4)
正如您在问题中所观察到的那样,正在调用varargs构造函数。这是因为Dice.__init__
的第二个定义是覆盖,而不是重载,第一个。
Python doesn't support method overloading,所以您至少有两个选择。
我更喜欢第二种方法,它允许您干净地分离您的逻辑。您还可以为工厂方法选择更具描述性的名称; from_n_sided_dice
比Dice
提供更多信息:
@staticmethod
def from_n_sided_dice(num_dice, sides):
return Dice([Die(sides)] * num_dice)
旁注:这真的是你想要的吗? [Die(sides)] * num_dice
返回一个列表,其中包含对同一Die对象的多个引用。相反,您可能需要[Die(sides) for _ in range(num_dice)]
。
编辑:您可以使用函数装饰器emulate method overloading(通过动态调度,而不是您可能习惯的静态调度,但Python中不存在静态类型)。您可能需要设计自己的解决方案以支持*args
和**kwargs
,并且使用具有更精确名称的单独方法通常仍然是更好的解决方案。
答案 1 :(得分:1)
您希望拥有的是单个__init__
方法,该方法按以下方式定义:
class Dice (object):
def __init__(self, *args):
if not isinstance(args[0], Die):
self.die_list = [Die(args[0]) for _ in range(args[1])]
else:
self.die_list = args
def roll(self):
return sum(x.roll() for x in self.die_list)