如何在 Python 元类中键入 __new__ 方法,以便 mypy 满意

问题描述 投票:0回答:1

我正在尝试在 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__
会得到类似的结果。

正确的做法是什么?

python python-typing metaclass
1个回答
10
投票

首先,返回类型是

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)
© www.soinside.com 2019 - 2024. All rights reserved.