我是Python的新手,也是OOP的新手。我有一个派生类,它从基类继承了几个类属性,其中一些是可变类型,而另一些是不可变的。派生类还继承了一个静态方法,该方法将类属性重置为其原始值。
这在基类中工作正常,并且在涉及可变类型类属性的派生类中不是问题。问题出现在不可改变的问题上。我知道无论如何我可能不得不完全重新设计它,但它确实提出了一个关于继承的问题,我找不到满意的答案。
以下是上述问题的简化说明:
class Parent(object):
boolean_attribute = True
list_attribute = ['1', '2', '3']
@staticmethod
def static_reset():
Parent.boolean_attribute = True
Parent.list_attribute = ['1', '2', '3']
class Child(Parent):
pass
print(Parent.list_attribute)
Parent.list_attribute.remove('1')
print(Parent.list_attribute)
Parent.static_reset()
print(Parent.list_attribute)
print(Parent.boolean_attribute)
Parent.boolean_attribute = False
print(Parent.boolean_attribute)
Parent.static_reset()
print(Parent.boolean_attribute)
print(Child.list_attribute)
Child.list_attribute.remove('1')
print(Child.list_attribute)
Child.static_reset()
print(Child.list_attribute)
print(Child.boolean_attribute)
Child.boolean_attribute = False
print(Child.boolean_attribute)
Child.static_reset()
print(Child.boolean_attribute)
以上输出如下:
['1', '2', '3']
['2', '3']
['1', '2', '3']
True
False
True
['1', '2', '3']
['2', '3']
['1', '2', '3']
True
False
False
请注意,static_reset方法在最后一种情况下没有工作。
对此处发生的事情的任何见解都将非常感激。
答案 0 :(得分:0)
当获取属性,并且该属性不存在时,将查询整个类层次结构。这就是继承在Python中的工作原理。
但是当设置属性时,它直接在对象(实例或类)上完成。这就是压倒一切的方式。
您已设置Child.boolean_attribute
属性,之前它不存在。这与变异 list_attribute
引用的列表不同;你永远不会设置那个属性。 Child.list_attribute
只有获取属性,之后您在列表对象(不是list.remove()
或Child
)上使用Parent
方法来更改内容。
如果您实际设置list_attribute
:
Child.list_attribute = ['foo', 'bar']
时,您会发现这种情况
>>> class Parent(object):
... boolean_attribute = True
... list_attribute = ['1', '2', '3']
...
>>> class Child(Parent):
... pass
...
>>> vars(Child)
dict_proxy({'__module__': '__main__', '__doc__': None})
>>> vars(Parent)
dict_proxy({'boolean_attribute': True, '__module__': '__main__', 'list_attribute': ['1', '2', '3'], '__dict__': <attribute '__dict__' of 'Parent' objects>, '__weakref__': <attribute '__weakref__' of 'Parent' objects>, '__doc__': None})
>>> Child.boolean_attribute = False
>>> vars(Child)
dict_proxy({'boolean_attribute': False, '__module__': '__main__', '__doc__': None})
请注意Child
现在也有boolean_attribute
条目。