假设我们正在实现一个元类,它需要在类实例化之前知道方法的解析顺序。
class Meta(type):
def __new__(cls, name, bases, namespace):
mro = ...除了重新实现C3算法之外,是否有一种计算mro的内置方法?
发布于 2018-09-20 14:13:40
更简单的方法是创建一个临时类,提取它的__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假设由于对层次结构上的一些超类的元类产生了疯狂的副作用,所以无法做到这一点,那么也有同样的想法,但是在实现之前,将基中的类克隆到“存根”类中--但可能的话,重新实现C3算法要比这更容易--当然也更高效,因为对于每个类来说,都会创建N*2个数的stub超类,其中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)(这个东西适用于我在交互模式下尝试过的基本案例-但是可能有一些复杂的边缘案例没有涵盖,包括多个元类等等)
https://stackoverflow.com/questions/52341247
复制相似问题