python模式装饰器中的奇怪类行为

时间:2019-05-29 08:18:25

标签: python oop abstract-class decorator

我想对英雄施加狂暴效果。 抽象类:AbstractEffect和AbstractPositive(后继类),可以接受基本参数。接下来,还将创建AbstractNegative。我不确定继承方案是否正确(英雄---> AbstractEffect)。

from abc import ABC, abstractmethod 
class Hero:
    def __init__(self):
        self.stats = {"HP": 128}
    def get_stats(self):
        return self.stats.copy()

class AbstractEffect(ABC):
    def __init__(self, base):
        self.base = base
    @abstractmethod
    def get_stats(self):
        return self.base.stats()

class AbstractPositive(AbstractEffect):
    def __init__(self, base):
        self.base = base
    @abstractmethod
    def get_stats(self):
        return self.base.stats()

class Berserk(AbstractPositive):
    def __init__(self, base):
        self.base = base
        self.stats= self.base.stats
        self.stats["HP"] += 7
    def get_stats(self):
        return self.stats


hero = Hero() 
brs1 = Berserk(hero) 
print('brs1', brs1.get_stats()) 
brs2 = Berserk(brs1) 
print('brs2', brs2.get_stats()) 
print('brs1', brs1.get_stats())

我想接收

brs1 {'HP': 135}
brs2 {'HP': 142}
brs1 {'HP': 135}

但我明白了

brs1 {'HP': 135}
brs2 {'HP': 142}
brs1 {'HP': 142}

我怎么了?

2 个答案:

答案 0 :(得分:1)

由于下面的代码

self.stats = {"HP": 128}

{“ HP”:128}是一个容器
并且,

self.stats = self.base.stats

因此,
当您使用Berserk(heroxxx)增强英雄时,self.stats["HP"] += 7实际上是在修改原始数据。因此,您需要将其更改为self.stats = self.base.get_stats(),然后才能获得所需的内容。您可以使用以下代码进行测试。

from abc import ABC, abstractmethod
class Hero:
    def __init__(self):
        self.stats = {"HP": 128}
    def get_stats(self):
        return self.stats.copy()

class AbstractEffect(ABC):
    def __init__(self, base):
        self.base = base
    @abstractmethod
    def get_stats(self):
        return self.base.stats

class AbstractPositive(AbstractEffect):
    def __init__(self, base):
        self.base = base
    @abstractmethod
    def get_stats(self):
        return self.base.stats

class Berserk(AbstractPositive):
    def __init__(self, base):
        self.base = base
        self.stats = self.base.get_stats()
        self.stats["HP"] += 7

    def get_stats(self):
        return self.stats.copy()


hero = Hero()
brs1 = Berserk(hero)
print('brs1', brs1.get_stats())
brs2 = Berserk(brs1)
print('brs2', brs2.get_stats())
print('brs1', brs1.get_stats())

答案 1 :(得分:0)

通过引用对您造成了残酷的殴打。

在您的代码中,您有self.stats = self.base.stats。这不会复制。因此,self.statsbrs1的{​​{1}}指的是相同 brs2。实例化dict时,您对其进行了更改,并且该更改反映在brs2中。

brs1是个不错的开始,如果您不希望这种情况发生。

也就是说,我觉得很奇怪,您想用这种方式编码状态效果...如果是我,我希望每个状态效果只包含一个修饰符,这取决于字符类。依次解决这些修饰符。