【发布时间】:2017-04-06 11:26:44
【问题描述】:
是否可以使用 get-set 属性覆盖元类的 __bases__ 字段(即派生自 type 的类)?以下代码适用于 getting C.__bases__,但不适用于 setting 它:
class Meta(type):
@property
def __bases__(cls):
print('Getting __bases__ via Meta.__bases__')
return super().__bases__
@__bases__.setter
def __bases__(cls, value):
print('Setting __bases__ via Meta.__bases__')
super().__bases__ = value
class A: pass
class B: pass
class C(A, B, metaclass=Meta): pass
# >>> C.__bases__
# Getting __bases__ via Meta.__bases__
# (<class '__main__.A'>, <class '__main__.B'>)
# >>> C.__bases__ = (B, A)
# Setting __bases__ via Meta.__bases__
# AttributeError: 'super' object has no attribute '__bases__'
我已经在 setter 函数中尝试了一些 super() 的替换,但它们都不起作用:
type.__setattr__(cls, '__bases__', value) 导致递归。
object.__setattr__(cls, '__bases__', value) 给TypeError: can't apply this __setattr__ to type object
所以,这归结为如何设置cls.__bases__ 字段
被元类上的属性所遮蔽。有什么想法吗?
(是的,我知道定义__bases__ 属性对类的实际__mro__ 没有影响,尽管可以通过覆盖mro() 来安排)
【问题讨论】:
-
不,你不能。为什么要这样做,这解决了什么问题?
-
而
super()只支持非数据描述符(所以只支持__get__)。不支持__set__,因此super().__bases__ = value将尝试在超级代理上设置__bases__属性,而不是在任何基类上。__bases__无法更改。 -
Re: 我为什么要这样做:想法是实现一种“类代理”,通过复制其
__mro__将方法和属性访问转发到代理类。如果类代理的__bases__也对应于代理类的__bases__,那就太好了,因此需要覆盖它。 -
设置
__bases__非常罕见,不支持应该没问题。
标签: python python-3.x inheritance metaclass