Enr*_*aud 6 python metaclass typing
我正在尝试__new__在 Python 的元类中键入该方法,以便它使 mypy 满意。代码将是这样的(取自pep-3115 - “Python 3000 中的元类”并精简了一点):
from __future__ import annotations
from typing import Type
# The metaclass
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[type], name: str, bases: tuple, classdict: dict) -> type:
result = type.__new__(cls, name, bases, classdict)
print('in __new__')
return result
class MyClass(metaclass=MetaClass):
pass
Run Code Online (Sandbox Code Playgroud)
有了这个,mypy 抱怨说,Incompatible return type for "__new__" (returns "type", but must return a subtype of "MetaClass"),指着线def __new__。
我也试过:
def __new__(cls: Type[MetaClass], name: str, bases: tuple, classdict: dict) -> MetaClass:
Run Code Online (Sandbox Code Playgroud)
然后mypy抱怨(约return result行)Incompatible return value type (got "type", expected "MetaClass")。
我也尝试过使用 var( TSubMetaclass = TypeVar('TSubMetaclass', bound='MetaClass'))类型,结果与使用MetaClass.
使用super().__new__而不是type.__new__给出了类似的结果。
什么是正确的方法呢?
首先,返回类型是MetaClass,不是type。其次,您需要显式转换返回值,因为type.__new__不知道它正在返回MetaClass. (它的具体返回类型由它的第一个参数决定,它不是静态已知的。)
from __future__ import annotations
from typing import Type, cast
# The metaclass
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[type], name: str, bases: tuple, classdict: dict) -> MetaClass:
result = type.__new__(cls, name, bases, classdict)
print('in __new__')
return cast(MetaClass, result)
class MyClass(metaclass=MetaClass):
passRun Code Online (Sandbox Code Playgroud)
使用时super,需要调整cls参数的静态类型。
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[MetaClass], name: str, bases: tuple, classdict: dict) -> MetaClass:
result = super().__new__(name, bases, classdict)
print('in __new__')
return cast(MetaClass, result)Run Code Online (Sandbox Code Playgroud)