【问题标题】:PyCharm type hinting custom list iterationPyCharm 类型提示自定义列表迭代
【发布时间】:2022-01-19 10:17:58
【问题描述】:

所以我创建了一个从list 继承的自定义类型,它在大多数情况下都很好用;虽然我注意到 Pycharm 在迭代自定义类的对象时无法找出类型提示。

我是这样定义的:

class MyList(list):

    def as_tuple(self):
        return tuple(self)

然后进行测试,我只创建一个简单的类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 类型时似乎无法提供类型提示:

到目前为止我最终所做的是在类定义中使用typing.Generic。我发现我还需要在类中实现自己的__iter__ 方法,这样我就可以对返回类型进行类型注释;否则,没有它似乎无法工作。

这是我目前的新变化:

from typing import Generic, TypeVar, Iterator


T = TypeVar('T')


class MyList(list, Generic[T]):

    def __iter__(self) -> Iterator[T]:
        return super().__iter__()

    ...

这显然可以解决问题:

所以问题是,有没有一种更简单的方法可以在 PyCharm 中通过 list 子类获取迭代类型提示,而无需按照我上面的方式进行设置?

我担心的另一个主要问题是对性能的轻微影响。例如,我以下面的代码为例对迭代进行计时,发现我使用的第二种方法速度较慢;不过这并不奇怪,因为我已经实现了一个自定义 __iter__,它引入了一个额外的方法调用。

from timeit import timeit

print(timeit("for o in objects: ...", globals=globals()))

我很想使用像元类解决方案这样复杂的东西,或者只是在类定义之外重新分配 MyList.__iter__ 方法,但我很想知道是否有人可以替代我上面使用的方法.

【问题讨论】:

    标签: python pycharm type-hinting python-typing


    【解决方案1】:

    您走在正确的道路上,但 python 类型提示的工作原理有点令人困惑。

    你需要做的就是这个,你不需要覆盖__iter__

    class MyList(list[T]):
        ...
    

    之所以有效,是因为您告诉 PyCharm 您正在创建一个继承泛型列表功能的类。

    另一方面,继承listGeneric 你告诉PyCharm 你想继承list 的能力,而不是通用list 的能力。相反,它是一个支持泛型并具有list 能力的类。

    至于性能,这仍然会损害性能,没关系。 Python 并不以高性能着称,如果您的代码确实需要快速,那么您应该考虑用 Cython 或 C 编写它并将其导入您的脚本或完全从 Python 迁移。

    【讨论】:

    • 哇,你就是那个男人!我很高兴解决方案实际上就是这么简单。也很惊讶我以前没有尝试过;出于某种原因,在线解决方案建议使用Generic[T],但后来我从来没有尝试过List[T],实际上,当您考虑它时,这会更加明显。无论如何,感谢您的帮助。
    猜你喜欢
    • 2018-07-15
    • 2015-05-01
    • 1970-01-01
    • 2019-03-17
    • 2021-09-08
    • 2013-12-26
    • 1970-01-01
    • 2020-11-23
    • 2021-06-19
    相关资源
    最近更新 更多