[英]How to type python class factory with linter?
我有这个代码
from abc import ABC
from typing import Type
class AbstractFoo(ABC):
"""Abstract foo."""
foo_attr: int
def foo_factory(foo_attr_val: int) -> Type[AbstractFoo]:
class Foo(AbstractFoo):
foo_attr = foo_attr_val
return Foo
FooA = foo_factory(5)
class FooB(FooA):
"""Public concrete foo."""
print(FooB.foo_attr)
这执行得很好,但后来我用mypy foo.py
运行 mypy,我得到一个看起来像的错误
foo.py:21: error: Variable "foo.FooA" is not valid as a type
foo.py:21: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
foo.py:21: error: Invalid base class "FooA"
Found 2 errors in 1 file (checked 1 source file)
我不明白这里有什么问题以及为什么这种类型无效。 解决这个问题的方法是什么?
我目前使用 Python 3.9,mypy 版本为 0.971。
您的问题是mypy
不支持动态基类(它们是否定义明确无关紧要)。 有关更多解决方法和详细信息,请参阅此mypy
问题。
如果你很高兴有一家工厂生产 class 而无需进行重大修改,你可以假装返回类型是class( 在线试一下! ):
from abc import ABC
from typing import Type
class AbstractFoo(ABC):
"""Abstract foo."""
foo_attr: int
def foo_factory(foo_attr_val: int) -> Type[AbstractFoo]:
class Foo(AbstractFoo):
foo_attr = foo_attr_val
return Foo
if TYPE_CHECKING:
FooA = AbstractFoo
else:
FooA = foo_factory(5)
class FooB(FooA):
"""Public concrete foo."""
print(FooB.foo_attr)
TYPE_CHECKING
是一个特殊常量,在运行时为False
,对于类型检查器为True
。 在这里你让类型检查器认为你的FooA
只是一个类型别名(在 py3.10+ 或使用typing_extensions
你甚至可以使用TypeAlias
类型注释使其显式)。
根据评论,这似乎是一个 mypy 问题。 我确实发现在 MAC 上使用 Python 3.10,代码仍然需要一些更改才能正确运行:
class AbstractFoo:
foo_attr: int
def foo_factory(foo_attr: int) -> type[AbstractFoo]:
class Foo(AbstractFoo):
AbstractFoo.foo_attr=foo_attr
return Foo
FooA = foo_factory(5)
class FooB(FooA):
pass
我做了两个改变:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.