Вот что я до сих пор:
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. Что я могу сделать здесь, чтобы сделать эту работу, или есть другая альтернатива?
Как вы заметили в своем вопросе, вызывается конструктор varargs. Это связано с тем, что второе определение Dice.__init__
является переопределяющим, а не перегружающим, первым.
Python не поддерживает перегрузку методов, поэтому у вас есть как минимум два варианта.
Я предпочитаю второй метод, который позволяет вам четко разделить вашу логику. Вы также можете выбрать более описательное имя для вашего метода factory; 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)]
.
EDIT: Вы можете эмулировать перегрузку метода (через динамическую отправку, а не статическую отправку, поскольку вы можете использовать to, но статические типы не существуют в Python) с декораторами функций. Возможно, вам придется разработать собственное решение для поддержки *args
и **kwargs
, а отдельные методы с более точными именами все же часто являются лучшим решением.
Die
в коде OP не имеют состояния, поэтому N копий одного и того же Die
должны давать те же результаты, что и N различных объектов Die
.
[Die.with_sides(sides)] * num_dice
.
То, что вы хотите иметь, - это единственный метод __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)
self.die_list
иногда делает self.die_list
кортежем, а список - другим. Я бы постарался сделать так же каждый раз.
die_list
- это набор целых чисел, которые проходят.