gpt4 book ai didi

python - 如何在给定基础的情况下恢复类的 mro?

转载 作者:行者123 更新时间:2023-11-28 18:08:25 24 4
gpt4 key购买 nike

假设我们正在实现一个元类,它需要在类被实例化之前知道方法解析顺序

class Meta(type):
def __new__(cls, name, bases, namespace):
mro = ...

有没有内置的方法来计算 mro,这是一种不同于重新实现 C3 algorithm 的方法?

最佳答案

更简单的方法是创建一个临时类,提取它的 __mro__,计算你的东西,然后真正创建元类:

class Meta(type):
def __new__(metacls, name, bases, namespace):
tmp_cls = super().__new__(metacls, name, bases, namespace)
mro = tmp_cls.__mro__
del tmp_cls # Not actually needed, just to show you are done with it.
...
# do stuff
...
new_class = super().__new__(metacls, name, bases, namespace)
...
return new_class

假设由于对层次结构中某些父类(super class)的元类的疯狂副作用而无法完成 - 然后是相同的想法,但在执行之前将基类中的类克隆为“ stub ”类它 - 但可能,重新实现 C3 算法比这更容易 - 而且肯定更有效,因为对于每个类,你会创建一个 N ** 2 个 stub 父类(super class),其中 N 是你的类层次结构的深度(嗯,这可能如果您选择这条路线,将被缓存)。

无论如何,它的代码可能是这样的:

stub_cache = {object: object}

def get_stub_class(cls):
# yields an mro-equivalent with no metaclass side-effects.
if cls is object:
return object
stub_bases = []
for base in cls.__bases__:
stub_bases.append(get_stub_class(base))
if cls not in stub_cache:
stub_cache[cls] = type(cls.__name__, tuple(stub_bases), {})
return stub_cache[cls]

def get_future_mro(name, bases):
stub_bases = tuple(get_stub_class(base) for base in bases)
stub_cls = type(name, stub_bases, {})
reversed_cache = {value:key for key, value in stub_cache.items()}
return [reversed_cache[mro_base] for mro_base in stub_cls.__mro__[1:]]

class Meta(type):
def __new__(metacls, name, bases, namespace):
mro = get_future_mro(name, bases)
print(mro)
return super().__new__(metacls, name, bases, namespace)

(这个东西适用于我在交互模式下尝试过的基本情况 - 但可能有未涵盖的复杂边缘情况,具有多个元类等)

关于python - 如何在给定基础的情况下恢复类的 mro?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52341247/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com