如何在 Python 元类中键入 __new__ 方法,以便 mypy 满意
How to type the __new__ method in a Python metaclass so that mypy is happy
我正在尝试在 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__
给出了相似的结果。
正确的做法是什么?
首先,return类型是MetaClass
,不是type
。其次,您需要显式转换 return 值,因为 type.__new__
不知道它是 returning MetaClass
的一个实例。 (它的特定 return 类型由它的第一个参数决定,静态未知。)
from __future__ import annotations
from typing import Type<b>, cast</b>
# The metaclass
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[type], name: str, bases: tuple, classdict: dict) -> <b>MetaClass</b>:
result = type.__new__(cls, name, bases, classdict)
print('in __new__')
return <b>cast(MetaClass, result)</b>
class MyClass(metaclass=MetaClass):
pass
要使用super
,需要调整cls
参数的静态类型。
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[<b>MetaClass</b>], name: str, bases: tuple, classdict: dict) -> MetaClass:
result = <b>super().__new__(name, bases, classdict)</b>
print('in __new__')
return cast(MetaClass, result)
我正在尝试在 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__
给出了相似的结果。
正确的做法是什么?
首先,return类型是MetaClass
,不是type
。其次,您需要显式转换 return 值,因为 type.__new__
不知道它是 returning MetaClass
的一个实例。 (它的特定 return 类型由它的第一个参数决定,静态未知。)
from __future__ import annotations
from typing import Type<b>, cast</b>
# The metaclass
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[type], name: str, bases: tuple, classdict: dict) -> <b>MetaClass</b>:
result = type.__new__(cls, name, bases, classdict)
print('in __new__')
return <b>cast(MetaClass, result)</b>
class MyClass(metaclass=MetaClass):
pass
要使用super
,需要调整cls
参数的静态类型。
class MetaClass(type):
# The metaclass invocation
def __new__(cls: Type[<b>MetaClass</b>], name: str, bases: tuple, classdict: dict) -> MetaClass:
result = <b>super().__new__(name, bases, classdict)</b>
print('in __new__')
return cast(MetaClass, result)