首页 > 解决方案 > 如何跨实例正确重置类变量

问题描述

dict 类变量在继承和实例化中被保留:

>>> class Superclass:
...   x = {'one': 1}
...   def __init__(self):
...     self.x['one'] += 1
... 
>>> class Subclass(Superclass):
...   def __init__(self):
...     super().__init__()
... 
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 3}
>>> Subclass().x
{'one': 4}
>>> Subclass().x
{'one': 5}
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 7}

我如何Superclass在每次实例化时强制使用新的字典,我希望:

>>> class Superclass:
...   x = {'one': 1}
...   def __init__(self):
...     self.x['one'] += 1
... 
>>> class Subclass(Superclass):
...   def __init__(self):
...     super().__init__()
... 
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}

并且

>>> class Superclass:
...   x = {'one': 1}
...   def __init__(self):
...     self.x['one'] += 1
... 
>>> class Subclass(Superclass):
...   x = {'one': 5}
...   def __init__(self):
...     super().__init__()
... 
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 6}
>>> Subclass().x
{'one': 6}

拥有一个实例变量显然是行不通的:

>>> class Superclass:
...   def __init__(self):
...     self.x = {'one': 1}
...     self.x['one'] += 1
... 
>>> class Subclass(Superclass):
...   def __init__(self):
...     self.x = {'one': 5}
...     super().__init__()
... 
>>> Subclass().x # desired: {'one': 6}
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}
>>> Subclass().x
{'one': 2}

当超类被重新实例化时,混合不起作用:

>>> class Superclass:
...   x = {'one': 1}
...   def __init__(self):
...     self.x['one'] += 1
... 
>>> class Subclass(Superclass):
...   def __init__(self):
...     self.x = {'one': 5}
...     super().__init__()
... 
>>> Superclass().x
{'one': 2}
>>> Superclass().x
{'one': 3}
>>> Superclass().x
{'one': 4}
>>> Superclass().x
{'one': 5}
>>> Superclass().x
{'one': 6}
>>> Superclass().x
{'one': 7}

解决此问题的正确且成熟的方法是什么?

标签: pythonpython-3.xinheritance

解决方案


You want subclasses to be able to override the code the superclass uses to construct its initial value of x, before it performs further modification. That's kind of a weird thing to override, but I would approach it by moving the construction of the initial x value into its own overridable method:

class Super:
    def __init__(self):
        self.x = self._initial_x()
        self.x['one'] += 1
    @classmethod
    def _initial_x(cls):
        return {'one': 1}

class Sub(Super):
    @classmethod
    def _initial_x(cls):
        return {'one': 5}

推荐阅读