获得原始班级的成员

时间:2015-02-22 17:50:42

标签: python

我正在编写一个可以通过特效修改内容的游戏。我决定使用python的能力来分配一个实例,而不是类。请注意,这是修改整个班级'成员,只是它的一个实例。把它想象成MtG的当地魅力。

我如何回到原班级的会员?

采用以下示例代码:

class Dog(object):
    noise = "Woof!"

    def bark(self):
        print self.noise

    def make_alpha(self):
        self.noise = self.noise.upper()

class Bulldog(Dog):
    noise = "Grr!"

class EnormousBulldog(Bulldog):
    pass

puppy = Dog()
print puppy.bark() # Woof!
bulldog = Bulldog()
print bulldog.bark() #Grr!
big_dog = EnormousBulldog()
print big_dog.bark() # Grr!

big_dog.make_alpha()
print puppy.bark() # Woof!
print bulldog.bark() # Grr!
print big_dog.bark() # GRR!

这一切都有效。

但是假设我想制作一个remove_alpha()方法。我可以尝试扭转make_alpha()对噪音的影响(因此在实际游戏中为每一种可能的特效做到这一点),但我感觉到这条道路是疯狂的。更简单的是回到Bulldog.noise。但是EnormousBulldog是如何得到Bulldog.noise的?

self.__dict__["noise"]会给我修改后的噪音。

EnormousBulldog.__dict__不会给我任何东西,因为噪音是Bulldog,它的超类。

type(self).__getattribute__(self, "noise")会看到有一个经过修改的噪音,而是给我这个。

我已考虑覆盖__getattribute__,而不是完全将实例更改为备用架构,但我认为性能损失并不值得。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

超类变量始终可用self.__class__.noiseEnormousBulldog.noisegetattr(self.__class__, 'noise')

或者,如果您的问题是"如何取消每个实例的更改",然后del来自实例的属性,可能还有一个警卫:

def remove_alpha(self):
    if 'noise' in self.__dict__:
        del self.noise

之后,属性查找会在超类中找到它。


不,不要将__getattr____getattribute__混淆;你想要覆盖前__getattr__;后者几乎肯定不是你想要做的。

答案 1 :(得分:1)

有一个相当肮脏和令人困惑的解决方案,但这可能会做你想要的:它依赖于在 class 属性之前评估实例属性的事实:

class Dog(object):
    noise = "Woof!"

    def bark(self):
        print self.noise

    def make_alpha(self):
        self.noise = self.__class__.noise.upper()

    def remove_alpha(self):
        try:
            del self.noise
        except AttributeError:
            print ("You tried to call remove_alpha into an"
                   " instance that doesn't have its own noise!!")

class Bulldog(Dog):
    noise = "Grr!"

if __name__ == '__main__':
    bulldog = Bulldog()
    bulldog.bark()
    print "Checkpoint: noise is NOT among the instance's vars: %s" % vars(bulldog)
    bulldog.make_alpha()
    print "Checkpoint: now noise is among the instance's vars: %s" % vars(bulldog)
    bulldog.bark()
    bulldog.remove_alpha()
    print "Checkpoint: noise is NOT among the instance's vars: %s" % vars(bulldog)
    bulldog.bark()

    print "Second test:"
    bulldog02 = Bulldog()
    bulldog02.bark()
    print "Checkpoint: noise is NOT among the instance's vars: %s" % vars(bulldog)
    bulldog02.remove_alpha()
    print "Checkpoint: noise is NOT among the instance's vars: %s" % vars(bulldog)
    bulldog02.bark() 

哪个输出:

Grr!
Checkpoint: noise is NOT among the instance's vars: {}
Checkpoint: now noise is among the instance's vars: {'noise': 'GRR!'}
GRR!
Checkpoint: noise is NOT among the instance's vars: {}
Grr!
Second test:
Grr!
Checkpoint: noise is NOT among the instance's vars: {}
You tried to call remove_alpha into an instance that doesn't have its own noise!!
Checkpoint: noise is NOT among the instance's vars: {}
Grr!

当您拨打make_alpha时,会在实例中添加一个新的noise属性,该属性会取代noise属性> class 级别。您可能想要检查内置vars的内容。

答案 2 :(得分:0)

我建议采用不同的方法,这会对性能产生一些影响,但会使代码更简单,更灵活:

class EnhancedAction(object):
    """
    A way to keep track of the enhanced implementation,
    as well as the original one, to allow to go back to it
    """

    def __init__(self, target, original, impl):
        self._target = target
        self._original = original
        self._impl = impl

    def __call__(self, *args):
        return self._impl(self._target, self._original, args)

    @property
    def original(self):
        return self._original


class Dog(object):
    noise = "Woof!"

    def bark(self):
        return self.noise

    def make_alpha(self):
        self.bark = EnhancedAction(
            target=self, original=self.bark,
            impl=lambda self, original, args: original().upper()
    )

    def revert_alpha(self):
        if isinstance(self.bark, EnhancedAction):
            self.bark = self.bark.original


class Bulldog(Dog):
    noise = "Grr!"


class EnormousBulldog(Bulldog):
    pass


big_dog = EnormousBulldog()
print "Regular bark:", big_dog.bark()  # Grr!
big_dog.make_alpha()
print "Enhanced bark:", big_dog.bark()  # GRR!
big_dog.revert_alpha()
print "Back to regular:", big_dog.bark()  # Grr!

<强>缺点

  • 另一层次的间接(表现命中)

<强>赞成

  • 您可以使用增强版
  • 调用原始实现
  • 您可以编写增强操作