- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是否可以使用 get-set 属性覆盖元类(即派生自 type
的类)的 __bases__
字段?以下代码适用于获取 C.__bases__
,但不适用于设置:
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()
不支持数据描述符,仅支持普通描述符,因为仅实现了 super().__get__
。
换句话说,赋值
super().__bases__ = value
失败,因为 super()
代理对象没有实现 descriptor.__set__()
method ,因此该赋值尝试将 __bases__
设置为该代理对象的属性。
您必须手动访问 type
对象上的描述符:
class Meta(type):
@property
def __bases__(cls):
print('Getting __bases__ via Meta.__bases__')
return type.__dict__['__bases__'].__get__(cls)
@__bases__.setter
def __bases__(cls, value):
print('Setting __bases__ via Meta.__bases__')
return type.__dict__['__bases__'].__set__(cls, value)
为了对称起见,我在 getter 中使用了相同的手动描述符访问,尽管 super().__bases__
也可以。
上面,我硬编码了type
而不是搜索MRO;您还可以使用辅助函数通过完整的 MRO 搜索找到正确的描述符:
class Meta(type):
def _find_super(cls, name):
mro = type(cls).__mro__
idx = mro.index(__class__)
for base in mro[idx + 1:]:
if name in base.__dict__:
return base.__dict__[name]
return
@property
def __bases__(cls):
print('Getting __bases__ via Meta.__bases__')
return cls._find_super('__bases__').__get__(cls)
@__bases__.setter
def __bases__(cls, value):
print('Setting __bases__ via Meta.__bases__')
return cls._find_super('__bases__').__set__(cls, value)
无论哪种方式,现在您都可以拦截正在设置的 __bases__
:
>>> 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__
>>> C.__bases__
Getting __bases__ via Meta.__bases__
(<class '__main__.B'>, <class '__main__.A'>)
关于python - 在元类中覆盖 __bases__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40747764/
是否可以使用 get-set 属性覆盖元类(即派生自 type 的类)的 __bases__ 字段?以下代码适用于获取 C.__bases__,但不适用于设置: class Meta(type):
在关于 Custom Classes 的部分的 The Python Language Reference据称: Special attributes: __name__ is the class n
类对象有一个 __bases__ (和一个 __base__ )属性: >>> class Foo(object): ... pass ... >>> Foo.__bases__ (,) 遗憾
以下代码在 Python 3.x 中不起作用,但它曾经用于旧式类: class Extender: def extension(self): print("Some work.
也许这是一个微不足道的问题。在 python 下,为什么 self.__class__.__bases__ 没有回溯到 object?我的只显示了类(class)之上的单亲 parent 的元组。 最
我找到了以下函数,但我不知道为什么需要额外的 __bases__ 扫描: def getMembersWithBases(classType): members = set(dir(class
我在 Python 的 REPL 中试过这个: >>> class Foo: ... def f():{} ... >>> >>> type(Foo) >>> Foo.__bases__ () >
我是一名优秀的程序员,十分优秀!