[英]How to type python class factory with linter?
I have this code我有这个代码
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)
This executes just fine, but then I run mypy with mypy foo.py
, I get an error that looks like这执行得很好,但后来我用
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)
I don't understand what is wrong here and why this type is invalid.我不明白这里有什么问题以及为什么这种类型无效。 What's the way to fix this?
解决这个问题的方法是什么?
I'm currently on Python 3.9 with mypy version 0.971.我目前使用 Python 3.9,mypy 版本为 0.971。
Your problem is that mypy
does not support dynamic base classes (doesn't matter if they are well-defined).您的问题是
mypy
不支持动态基类(它们是否定义明确无关紧要)。 See this mypy
issue for more workarounds and details.有关更多解决方法和详细信息,请参阅此
mypy
问题。
If you're happy enough to have a factory producing class without major modifications, you can just pretend that return type is that class ( try me online! ):如果你很高兴有一家工厂生产 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
is a special constant that is False
at runtime and True
for type checkers. TYPE_CHECKING
是一个特殊常量,在运行时为False
,对于类型检查器为True
。 Here you make type checker think that your FooA
is just a type alias (and on py3.10+ or with typing_extensions
you can even make it explicit with TypeAlias
type annotation).在这里你让类型检查器认为你的
FooA
只是一个类型别名(在 py3.10+ 或使用typing_extensions
你甚至可以使用TypeAlias
类型注释使其显式)。
Based on the comments, it appears as if this is a mypy issue.根据评论,这似乎是一个 mypy 问题。 I did find that with Python 3.10 on MAC, the code still required some changes to run correctly:
我确实发现在 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
I made two changes:我做了两个改变:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.