PyCharm 类型提示自定义列表迭代
PyCharm type hinting custom list iteration
所以我创建了一个自定义类型,它是 list
的子class,在大多数情况下效果很好;尽管我注意到 Pycharm 在迭代自定义 class.
的对象时无法确定类型提示
我是这样定义的:
class MyList(list):
def as_tuple(self):
return tuple(self)
然后为了测试,我只创建了一个简单的 class A
然后创建了一堆 A
对象:
from dataclasses import dataclass
@dataclass
class A:
f1: str
f2: int
objects: MyList[A] = MyList([
A('hello', 111),
A('world', 222)
])
我认为类型提示可能是不必要的,因为看起来 PyCharm 在任何情况下都正确地将其识别为 MyList[A]
。
出于类型提示的目的,访问元素似乎工作正常:
但是 PyCharm 在遍历 list
类型时似乎无法提供类型提示:
到目前为止我最终做的事情 是在class 定义中使用typing.Generic
。我发现我还需要在 class 中实现我自己的 __iter__
方法,这样我就可以键入注释 return 类型;否则,没有它似乎无法工作。
这是我到目前为止的新变化:
from typing import Generic, TypeVar, Iterator
T = TypeVar('T')
class MyList(list, Generic[T]):
def __iter__(self) -> Iterator[T]:
return super().__iter__()
...
这显然可以解决问题:
所以问题是,是否有一种更简单的方法可以在 PyCharm 中通过 list
subclass 获取迭代类型提示,而无需按照我的方式进行设置以上?
我主要担心的另一个问题是对性能的轻微影响。例如,我使用以下代码作为示例对迭代进行计时,发现我使用的第二种方法速度较慢;不过这并不奇怪,因为我已经实现了一个自定义 __iter__
,它引入了一个额外的方法调用。
from timeit import timeit
print(timeit("for o in objects: ...", globals=globals()))
我很想使用像 metaclass 解决方案这样复杂的东西,或者可能只是在 class 定义之外重新分配 MyList.__iter__
方法,但我想看看是否任何人都可以替代我上面使用的方法。
您走在正确的道路上,但有点令人困惑 python 类型提示的工作原理。
您需要做的就是这个,您不需要覆盖 __iter__
。
class MyList(list[T]):
...
之所以可行,是因为您告诉 PyCharm 您正在创建一个 class 来继承通用列表的功能。
另一方面,继承 list
和 Generic
你告诉 PyCharm 你想继承 list
的能力,而不是通用 [=12] 的能力=].相反,它是 class 支持泛型并具有 list
能力。
至于性能,这仍然会影响性能,这没关系。 Python 并不以高性能而著称,如果您的代码确实需要快速,那么您应该考虑用 Cython 或 C 编写它并将其导入您的脚本或完全远离 Python。
所以我创建了一个自定义类型,它是 list
的子class,在大多数情况下效果很好;尽管我注意到 Pycharm 在迭代自定义 class.
我是这样定义的:
class MyList(list):
def as_tuple(self):
return tuple(self)
然后为了测试,我只创建了一个简单的 class A
然后创建了一堆 A
对象:
from dataclasses import dataclass
@dataclass
class A:
f1: str
f2: int
objects: MyList[A] = MyList([
A('hello', 111),
A('world', 222)
])
我认为类型提示可能是不必要的,因为看起来 PyCharm 在任何情况下都正确地将其识别为 MyList[A]
。
出于类型提示的目的,访问元素似乎工作正常:
但是 PyCharm 在遍历 list
类型时似乎无法提供类型提示:
到目前为止我最终做的事情 是在class 定义中使用typing.Generic
。我发现我还需要在 class 中实现我自己的 __iter__
方法,这样我就可以键入注释 return 类型;否则,没有它似乎无法工作。
这是我到目前为止的新变化:
from typing import Generic, TypeVar, Iterator
T = TypeVar('T')
class MyList(list, Generic[T]):
def __iter__(self) -> Iterator[T]:
return super().__iter__()
...
这显然可以解决问题:
所以问题是,是否有一种更简单的方法可以在 PyCharm 中通过 list
subclass 获取迭代类型提示,而无需按照我的方式进行设置以上?
我主要担心的另一个问题是对性能的轻微影响。例如,我使用以下代码作为示例对迭代进行计时,发现我使用的第二种方法速度较慢;不过这并不奇怪,因为我已经实现了一个自定义 __iter__
,它引入了一个额外的方法调用。
from timeit import timeit
print(timeit("for o in objects: ...", globals=globals()))
我很想使用像 metaclass 解决方案这样复杂的东西,或者可能只是在 class 定义之外重新分配 MyList.__iter__
方法,但我想看看是否任何人都可以替代我上面使用的方法。
您走在正确的道路上,但有点令人困惑 python 类型提示的工作原理。
您需要做的就是这个,您不需要覆盖 __iter__
。
class MyList(list[T]):
...
之所以可行,是因为您告诉 PyCharm 您正在创建一个 class 来继承通用列表的功能。
另一方面,继承 list
和 Generic
你告诉 PyCharm 你想继承 list
的能力,而不是通用 [=12] 的能力=].相反,它是 class 支持泛型并具有 list
能力。
至于性能,这仍然会影响性能,这没关系。 Python 并不以高性能而著称,如果您的代码确实需要快速,那么您应该考虑用 Cython 或 C 编写它并将其导入您的脚本或完全远离 Python。