使用自定义对象进行多分类并模拟容器类型

时间:2015-03-12 16:03:14

标签: python methods subclass

实际例子:所以我有一个单面的六面骰子(d6),我将与其他3个人一起收集4个六面骰子(4d6)。当然,我可以一次滚动1d6,但我宁愿在'同一时间'滚动4d6。

所以这是我的component.py模块,它包含一个Component类。这本身基本上是一个空类(它有一个名称属性),所以这不应该影响这个问题的其余部分:

class Die(Component):

    def __init__(self, sides=6, start=1, stop=6):
        super(Die, self).__init__()
        self.sides = sides
        self.start = start
        self.stop = stop

    def roll(self):
        die_range = self.stop - self.start + 1
        result = randrange(self.start, self.stop, die_range/self.sides)
        return result

我希望最终能够在game.py脚本中写出与此类似的内容,如下所示:

from component import Dice

my_dice = Dice(count=4)
my_dice.append(Dice(count=3, sides=12, stop=12))
print(my_dice.roll())

我希望输出看起来像:

4, 2, 3, 1, 7, 12, 8

我对关注使输出看起来不错。我可以弄清楚;我刚刚在完整的背景下给出了它。

所以这就是我为Dice类编写的内容:

class Dice(Die, object):
    def __init__(self, container=None, count=0, **kwargs):
        super(Dice, self).__init__()
        if container is None:
            container = []
        if kwargs is not None:
            for x in range(count):
                container.append(Die(**kwargs))

        self.container = container

    def append(self, item):
        if hasattr(item, 'container'):
            self.container.extend(item.container)
        elif issubclass(item, Die):
            self.container.append(item.container)
        else:
            raise Exception(TypeError)

    def __str__(self):
        return str(self.container)

    def __repr__(self):
        return str(self.container)

    def __getitem__(self, key):
        return Dice(self.container[key])

    def __len__(self):
        return len(self.container)

    def roll(self):
        results = []
        for die in self.container:
            results.append(die.roll())
        return results

这是好设计吗?我不相信它是这样或那样的。

如果有人对应用程序感兴趣,我正在构建一个桌面游戏框架,我想要其他人可以轻松子类化的通用类,以便更快地制作游戏。

1 个答案:

答案 0 :(得分:0)

  • 首先,我认为,使用像Die这样的密切类名称是令人困惑且容易出错的。我和Die& DiceSet。

    class Dice(Die, object):
    
  • 我不明白Dice从Die那里继承了什么,它真的需要继承它吗?

    if hasattr(item, 'container'):
        self.container.extend(item.container)
    
  • 看起来不可靠,所以某些类的每个对象都有" container"将被添加到Dice容器中......检查它是否是Dice的子类会更好吗?

    elif issubclass(item, Die):
        self.container.append(item.container)
    
  • 我认为这是一些复制粘贴错误,因为Die不应该有任何容器,所以只有append(item)

     result = randrange(self.start, self.stop, die_range/self.sides)
    
  • 我不确定步骤的计算。步骤永远不应该是分数。我认为应该始终" 1":

    result = randrange(self.start, self.stop, 1)
    
  • 并且双方的数量没有发挥作用。您只需要它来检查开始停止是否。当然,您缺少检查 start 而不是停止。并且您可以使用 sides 来默认初始化 stop (如果没有给出)。

  • 您可以将Die的最后结果存储为Die的私有属性:将其初始化为 start Die 中的随机值。{{1} (最多设计),然后将其保存在 roll 中。所以你可以覆盖Die中的表示:

    __init__

然后修改Dice的表示形式:

def __repr__(self):
     print str(self.last_result)

因此,在打印Dice对象时,您将获得一组数字。