我需要创建一个类型,其行为类似于typing.Any类型检查器(mypy)查看时的行为,但与typing.Any.
用例是一些漂亮的“元”代码,需要从一组可以用 注释的其他变量中找到用此类型注释的变量typing.Any。请注意,我永远不需要实际创建此类型的实例,我只需要它在数据类上下文中进行类型注释。例子:
from dataclasses import dataclass, fields
from typing import Any
MyAny = ... # What to put here?
@dataclass()
class Test:
a: Any
b: MyAny = None
for field in fields(Test):
if field.type == MyAny:
print(f"It's {field.name}") # This should print "It's b"
Run Code Online (Sandbox Code Playgroud)
我尝试过的事情:
不起作用,因为你不能继承 Any:TypeError: Cannot subclass <class 'typing._SpecialForm'>
class MyAny(Any):
pass
Run Code Online (Sandbox Code Playgroud)不起作用,因为它与正常的 Any 没有区别(上面代码片段的结果是It's a\nIt's b)
MyAny = Any
Run Code Online (Sandbox Code Playgroud)在运行时工作,但 mypy 抱怨默认值:
Mypy: Incompatible types in assignment …
Python 标准库multiprocessing.Event被明确声明为克隆threading.Event并具有相同的接口。我想注释变量和参数,以便它们可以接受这些类中的任何一个,并对mypy它们进行类型检查。我尝试创建一个协议(我使用了它,multiprocessing.synchronize.Event因为这是由 返回的实际类multiprocessing.Event)。
import multiprocessing
import threading
from typing import Optional, Type, Protocol
class Event(Protocol):
def wait(self, timeout: Optional[float]) -> bool:
...
def set(self) -> None:
...
def clear(self) -> None:
...
def is_set(self) -> bool:
...
class Base:
flag_class: Type[Event]
def foo(self, e: Event):
pass
class DerivedOne(Base):
flag_class = multiprocessing.synchronize.Event
def foo(self, e: multiprocessing.synchronize.Event):
pass
class DerivedTwo(Base):
flag_class = threading.Event
def foo(self, e: threading.Event):
pass
Run Code Online (Sandbox Code Playgroud)
然而,mypy(版本 0.761)无法识别这一点 …
有人可以解释为什么这段代码虽然有效,但却使 mypy 静态分析器以多种方式抱怨:
ranges = dict()
ranges['max'] = 0
ranges['services'] = []
ranges['services'].append('a')
Run Code Online (Sandbox Code Playgroud)
即:
ranges = dict()
ranges['max'] = 0
ranges['services'] = []
ranges['services'].append('a')
Run Code Online (Sandbox Code Playgroud)
如果我简单地向初始变量添加类型提示,ranges: dict = dict()它就可以正常工作。
我很困惑为什么静态分析器不能自己解决这个问题,特别是当我dict在第一个实例中使用关键字来初始化字典时。
您可以\xe2\x80\x99t 使用类型类型,例如Dict[str, int]在检查中isinstance:
Python 3.7.6 (default, Dec 30 2019, 19:38:28)\nType \'copyright\', \'credits\' or \'license\' for more information\nIPython 7.12.0 -- An enhanced Interactive Python. Type \'?\' for help.\n\nIn [1]: from typing import Dict\n\nIn [2]: myvar = {"a": 1}\n\nIn [3]: isinstance(myvar, Dict[str, int])\n---------------------------------------------------------------------------\nTypeError Traceback (most recent call last)\n<ipython-input-3-a8fee57141ae> in <module>\n----> 1 isinstance(myvar, Dict[str, int])\nRun Code Online (Sandbox Code Playgroud)\n\n然而,任何进行类型检查的库都需要能够执行类似的操作isinstance(myvar, Dict[str, int])(...我意识到它应该被称为与 不同的东西isinstance,这不是完全相同的事情)
我觉得适用于打字的等效函数必须存在于某个地方,也许在mypy项目中?(但是里面\xe2\x80\x99s有很多复杂的代码,到目前为止我找不到\xe2\x80\x99)
\n\n除了 mypy 之外,还有很多项目需要这个,例如像pydantic和 AFAICT 这样的库,它们都有复杂的手动实现,并且似乎有很多边缘情况(或者只是 …
在下面的代码中,我有一个可以接受字符串或某些TextIOBase. 如果传递一个字符串,它将被解释为应该打开和读取的文件的路径。如果TextIOBase传递 a,则将读取该流的内容:
from typing import Union
import io
def function(foo: Union[str, io.TextIOBase]) -> None:
if isinstance(foo, str):
foo = open(foo, "w")
Run Code Online (Sandbox Code Playgroud)
这看起来应该没问题,因为 Union 应该是协变的,这意味着 union 中类型之一的子类应该满足类型注释,在这种情况下, 的输出类型是 的子open()类TextIOBase。然而,mypy 抱怨:
from typing import Union
import io
def function(foo: Union[str, io.TextIOBase]) -> None:
if isinstance(foo, str):
foo = open(foo, "w")
Run Code Online (Sandbox Code Playgroud)
open()我认为根据传递的参数,返回类型的歧义可能存在问题,因此我尝试改为使用 a StringIO,但得到了相同的错误。有什么想法吗?mypy 为什么对我生气?
我还尝试过使用一些玩具类(例如Union[str, T1],然后分配一个T2,其中T2是 T1 的子类),mypy对此非常满意。
我创建了一个类似字典的自定义类来简化跨大型数据集的评估指标的合并。此类实现了一种__add__总结各种指标的方法。
这是我正在处理的代码的简化版本:
from __future__ import annotations
from typing import TypeVar, Dict
T = TypeVar('T', int, float)
class AddableDict(Dict[str, T]):
def __add__(self, other: AddableDict[T]) -> AddableDict[T]:
if not isinstance(other, self.__class__):
raise ValueError()
new_dict = self.__class__()
all_keys = set(list(self.keys()) + list(other.keys()))
for key in all_keys:
new_dict[key] = self.get(key, 0) + other.get(key, 0)
return new_dict
# AddableIntDict = AddableDict[int]
# this would work just fine, however I need to add a few additional methods
class AddableIntDict(AddableDict[int]):
def some_int_specific_method(self) -> None:
pass …Run Code Online (Sandbox Code Playgroud) 我想为异步函数编写一个装饰器。如何注释装饰器定义的类型?
这是我想做的一个例子:
from typing import TypeVar # will Awaitable help?
AsyncFn = TypeVar('AsyncFn') # how to narrow this type definition down to async functions?
def my_decorator(to_decorate: AsyncFn) -> AsyncFn:
async def decorated(*args, **kwargs): # mypy keeps saying "Function is missing a type"
return await to_decorate(*args, **kwargs)
@my_decorator
async def foo(bar: int) -> str:
return f"async: {bar}"
@my_decorator
async def quux(spam: str, **eggs: str) -> None:
return
foo(1) # should check
foo("baz") # mypy should yell
quux("spam") # should check
quux(1) …Run Code Online (Sandbox Code Playgroud) 我正在与 mypy 作斗争,不明白我想要传递一个派生类,其中代码接受基类或任何派生类的实例,并在该传递的实例上调用方法。
我的代码:
from typing import Type
import abc
class Base(abc.ABC):
@abc.abstractmethod
def my_method(self):
pass
class Derived(Base):
def my_method(self):
print("Derived")
def my_function(b: Type[Base]):
b.my_method() # line 14
d = Derived()
my_function(d) # line 17
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它会打印“Derived”(如预期)。但 mypy 对此并不满意:
mcve.py:14:错误:“Base”的“my_method”参数太少
mcve.py:17: 错误:“my_function”的参数 1 具有不兼容的类型“Derived”;预期“类型[基础]”
我假设第 14 行错误是因为 mypy 没有看到第一个参数位于方法调用前面( )base.,这可能是因为第 17 行的错误?
我如何让 mypy 理解这段代码?或者我在这里缺少什么?
考虑当我有不同的类实现相同的方法但返回不同类型时的情况。
class A:
def method(self) -> float:
return 3.14
class B:
def method(self) -> str:
return 'a string'
def do_method(x):
return x.method()
r = do_method(A())
reveal_type(r) # Revealed type is 'Any'
Run Code Online (Sandbox Code Playgroud)
Mypy 无法推断函数的确切返回类型do_method(),这取决于其参数x。我如何帮助 Mypy 实现这一目标?
注意:还请考虑到我想与该函数一起使用的此类类的数量do_method()太多,因此不想将它们全部更改。
我正在尝试创建一个函数,它接受哺乳动物列表或动物列表作为参数。
这是我的代码
from typing import Union, List
class Animals():
pass
class Mammels(Animals):
pass
def add_mammel(x : List[Union[Animals, Mammels]]):
x.append(Mammels())
l = [Mammels(), Mammels()]
add_mammel(l)
print(l)
Run Code Online (Sandbox Code Playgroud)
这段代码有效,但是当我用 mypy 检查它时,我得到以下内容
python -m mypy fourth.py
fourth.py:11: error: Argument 1 to "add_mammel" has incompatible type "List[Mammels]"; expected "List[Union[Animals, Mammels]]"
fourth.py:11: note: "List" is invariant -- see http://mypy.readthedocs.io/en/latest/common_issues.html#variance
fourth.py:11: note: Consider using "Sequence" instead, which is covariant
Run Code Online (Sandbox Code Playgroud)
这个问题与“方差”有关,但我无法弄清楚这真正意味着什么。