获取原始类的memb

2024-05-31 23:56:27 发布

您现在位置: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\u alpha()方法。我可以尝试反转make_alpha()对噪音的影响(因此在实际游戏中对每个可能的特殊效果都这样做),但我感觉到在这条路上有疯狂。更简单的方法是回到斗牛犬。噪音. 但是大斗牛犬是怎么做到的呢斗牛犬。噪音?你知道吗

self.__dict__["noise"]将给出修改后的噪声。你知道吗

EnormousBulldog.__dict__不会给我任何信息,因为噪声在Bulldog中,它的超类。你知道吗

type(self).__getattribute__(self, "noise")将看到有一个修改过的噪声,并给我这个代替。你知道吗

我考虑过重写__getattribute__,而不是将实例作为一个完全替代的体系结构来更改,但我认为性能上的损失是不值得的。你知道吗

有什么想法吗?你知道吗


Tags: 实例selfalphamakeclassprintnoisedog
3条回答

超类变量始终可用作self.__class__.noiseEnormousBulldog.noisegetattr(self.__class__, 'noise')。你知道吗

或者,如果您的问题是“如何取消每个实例的更改”,那么del实例的属性,可能带有一个保护:

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

之后,属性查找将在超类中找到它。你知道吗


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

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

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!

缺点:

  • 又一个间接层次(性能命中)

优点:

  • 您可以从增强的实现调用原始实现
  • 您可以执行增强的操作

有一个相当肮脏和混乱的解决方案,但这可能会满足您的需要:它依赖于这样一个事实,即在属性之前对实例属性求值:

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属性。您可能需要检查内置的vars做什么。你知道吗

相关问题 更多 >