从列表子类化时迭代器表现良好,但从双端队列子类化时则不然 - Python

发布于 2025-01-16 09:58:14 字数 588 浏览 5 评论 0原文

我想创建一个“循环列表”对象:我可以通过它循环地、永远地迭代。为此,我尝试对 list 类进行子类化:

from itertools import cycle 

class Circle(list):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __iter__(self):
        sup_iter = super().__iter__()
        return cycle(sup_iter)

事实上,它工作得非常好(在某种程度上。不可能将其转换回 list ,正如一些答案所指出的那样)。但是,如果我尝试将我的类基于 deque 类,我似乎不再能够 在我的对象上调用我的 strrepr 因为这样做会使 python 解释器冻结,并且该进程最终被终止。请记住,当类继承自 list 时,所有这些都不会发生。

我很茫然,任何人都可以帮助阐明正在发生的事情吗?

I would like to create a "circular list" object: one through which I could iterate, cyclically, forever. To that effect, I attempted to subclass the list class as such:

from itertools import cycle 

class Circle(list):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __iter__(self):
        sup_iter = super().__iter__()
        return cycle(sup_iter)

And, indeed, it works wonderfully (to an extent. It's not possible to convert it back to a list, as some answers have pointed out). If, however, I attempt to base my class on the deque class, I can seemingly no longer
call my str or repr on my objects
as doing so makes the python interpreter freeze, and the process eventually gets killed. Bear in mind that none of it happens when the class inherits from list.

I am at a loss, can anyone help shed some light into what's going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再可℃爱ぅ一点好了 2025-01-23 09:58:15

CPython 中的列表 repr 定义如下: https ://github.com/python/cpython/blob/v3.10.3/Objects/listobject.c#L361-L415

重要的一点是这个循环使用

for (i = 0; i < Py_SIZE(v); ++i) { ...

并且您根本不会覆盖对象的大小,因此就列表表示而言,Circle([1,2,3]) 仍然具有 3 个元素。循环对每个元素执行一次 repr,然后结束。

CPython 中的 deque repr 定义如下: https://github.com/python/cpython/blob/v3.10.3/Modules/_collectionsmodule.c#L1376-L1404

重要的一点是,此代码使用

aslist = PySequence_List(deque);

,即它首先将双端队列表示为列表,对于您的 Circle 类来说,这将是一个无限循环,最终会消耗所有可用内存并导致计算机冻结。

The list repr in CPython is defined here: https://github.com/python/cpython/blob/v3.10.3/Objects/listobject.c#L361-L415

The important point is that this loop uses

for (i = 0; i < Py_SIZE(v); ++i) { ...

and you don't override the size of the object at all, so a Circle([1,2,3]) still has 3 elements as far as the list repr is concerned. The loop does a repr on each element, and then finishes.

The deque repr in CPython is defined here: https://github.com/python/cpython/blob/v3.10.3/Modules/_collectionsmodule.c#L1376-L1404

The important point is that this code uses

aslist = PySequence_List(deque);

i.e. it first represents the deque as a list, which for your Circle class will be an infinite loop, eventually consuming all memory available and appearing to freeze your computer.

骄傲 2025-01-23 09:58:15

两者都将它们转换为列表并调用 repr ( 这将尝试转换在构建 repr 字符串的过程中将其添加到列表)将尝试迭代双端队列。

但你通过让迭代永远不会结束来“打破”这一点。

有人可能会说执行此操作的代码(最终,此处< /a>) 可以查看对象的长度(如果有一个,不是所有的都会)并在这么多元素之后停止,但它不会:

    /* Run iterator to exhaustion. */
    for (;;) {
        PyObject *item = iternext(it);
        ...

IMO,你最好离开 __iter__按原样和在您想要迭代循环列表的地方使用cycle(your_circle)

Both converting them to lists and calling repr (which will try to convert it to a list in the process of building a repr string) will attempt to iterate over the deque.

But you've "broken" this by making iteration never end.

One might say that the code that does this (eventually, here) could look at the length of the object (if it had one, not all would) and stop after that many elements, but it does not:

    /* Run iterator to exhaustion. */
    for (;;) {
        PyObject *item = iternext(it);
        ...

IMO, you're better off leaving __iter__ as-is and using cycle(your_circle) where you want to iterate over your circular list.

深居我梦 2025-01-23 09:58:15

当然,您不能在无限迭代器上调用 list 。迭代器上 list 的定义是,它不断读取元素,直到迭代器告诉它没有更多元素为止。

你知道itertools.cycle吗?

Of course you can't call list on an infinite iterator. The definition of list on an iterator is that it keeps on reading elements until the iterator tells it there are no more.

Do you know about itertools.cycle?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文