我正在尝试在 Python 的元类中输入
__new__
方法,以便它能让 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
有了这个,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:
然后 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):
pass
要使用
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)