从子类主体访问父类属性

war*_*iuc 20 python python-3.x

我有一个Klass类属性的类my_list.我有一个子类SubKlass,我希望有一个类属性my_list,它是父类中相同属性的修改版本:

class Klass():
    my_list = [1, 2, 3]


class SubKlass(Klass):
    my_list = Klass.my_list + [4, 5] # this works, but i must specify parent class explicitly
    #my_list = super().my_list + [4, 5] # SystemError: super(): __class__ cell not found
    #my_list = my_list + [4, 5] # NameError: name 'my_list' is not defined 


print(Klass.my_list)
print(SubKlass.my_list)
Run Code Online (Sandbox Code Playgroud)

那么,有没有办法访问父类属性而不指定其名称?

更新:

Python问题跟踪器上有一个错误:http://bugs.python.org/issue11339.我们希望它能在某个时刻得到解决.

Kat*_*iel 12

你不能.

Python中的类定义工作原理如下.

  1. 解释器看到一个class语句后跟一段代码.

  2. 它创建一个新的命名空间并在命名空间中执行该代码.

  3. type使用生成的命名空间,类名,基类和元类(如果适用)调用内置函数.

  4. 它将结果分配给类的名称.

在类定义中运行代码时,您不知道基类是什么,因此您无法获取其属性.

可以做的是在定义类后立即修改类.


编辑:这是一个小类装饰器,您可以用来更新属性.这个想法是你给它一个名字和一个功能.它查看了类的所有基类,并使用该名称获取其属性.然后它使用从基类继承的值列表和您在子类中定义的值调用该函数.此调用的结果与名称绑定.

代码可能更有意义:

>>> def inherit_attribute(name, f):
...     def decorator(cls):
...             old_value = getattr(cls, name)
...             new_value = f([getattr(base, name) for base in cls.__bases__], old_value)
...             setattr(cls, name, new_value)
...             return cls
...     return decorator
... 
>>> def update_x(base_values, my_value):
...    return sum(base_values + [my_value], tuple())
... 
>>> class Foo: x = (1,)
... 
>>> @inherit_attribute('x', update_x)
... class Bar(Foo): x = (2,)
... 
>>> Bar.x
(1, 2)
Run Code Online (Sandbox Code Playgroud)

这个想法是,你确定x(2,)Bar.然后,装饰者将查看子类Bar,查找所有xs,并update_x与它们一起调用.所以它会打电话

update_x([(1,)], (2,))
Run Code Online (Sandbox Code Playgroud)

它通过连接它们来组合它们,然后将它x再次绑定.那有意义吗?

  • 请注意,元类劫持#3,甚至可以在将它传递给`type`之前修改`bases`.所以是的,你做不到. (2认同)