我有一个函数,它对它的一个参数使用len
函数,并迭代该参数。现在我可以选择是用Iterable
来注释类型,还是用Sized
来注释类型,但是这两种方法都会在mypy
中给出错误。在
from typing import Sized, Iterable
def foo(some_thing: Iterable):
print(len(some_thing))
for part in some_thing:
print(part)
给予
^{pr2}$同时
def foo(some_thing: Sized):
...
给予
error: Iterable expected
error: "Sized" has no attribute "__iter__"
由于没有this issue中讨论的Intersection
,我需要一些混合类。在
from abc import ABCMeta
from typing import Sized, Iterable
class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):
pass
def foo(some_thing: SizedIterable):
print(len(some_thing))
for part in some_thing:
print(part)
foo(['a', 'b', 'c'])
当将foo
与list
一起使用时,会出现错误。在
error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"
这并不奇怪,因为:
>>> SizedIterable.__subclasscheck__(list)
False
所以我定义了一个__subclasshook__
(参见docs)。在
class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):
@classmethod
def __subclasshook__(cls, subclass):
return Sized.__subclasscheck__(subclass) and Iterable.__subclasscheck__(subclass)
然后子类检查起作用:
>>> SizedIterable.__subclasscheck__(list)
True
但是mypy
仍然抱怨我的list
。在
error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"
当同时使用len
函数并迭代我的参数时,如何使用类型提示?我认为铸造foo(cast(SizedIterable, ['a', 'b', 'c']))
不是一个好的解决方案。在
如果计划只使用list或tuple并按索引访问其元素,比如},请参见here。在
x[0]
,那么应该使用Sequence
from{a1}。Sequence
同时是Sized
和{从Python3.6开始有一个新的类型叫做
Collection
。见here。在将来将引入} 提供。另请参见PEP 544。使用
Protocol
s。它们已经通过^{Protocol
以上代码将是:mypy
毫无怨言地接受该代码。但是PyCharm说关于最后一行。在
相关问题 更多 >
编程相关推荐