从itertools.cycle中提取列表 [英] Extract a list from itertools.cycle

查看:62
本文介绍了从itertools.cycle中提取列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含itertools.cycle实例的类,我希望能够复制该实例.一种方法(我唯一能想到的一种方法)是提取初始可迭代方法(这是一个列表),并存储循环所处的位置.

I have a class which contains a itertools.cycle instance which I would like to be able to copy. One approach (the only one I can come up with), is to extract the initial iterable (which was a list), and store the position that the cycle is at.

不幸的是,我无法掌握用于创建循环实例的列表,似乎也没有一种明显的方法:

Unfortunately I am unable to get hold of the list which I used to create the cycle instance, nor does there seem to be an obvious way to do it:

import itertools
c = itertools.cycle([1, 2, 3])
print dir(c)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', 
 '__hash__', '__init__', '__iter__', '__new__', '__reduce__', 
 '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
 '__subclasshook__', 'next']

我可以提出一些合理的理由,为什么某些类型的输入可迭代项不允许这样做,但是对于一个元组甚至一个列表(可变性可能是一个问题),我不明白为什么会这样不可能.

I can come up with some half reasonable reasons why this would be disallowed for some types of input iterables, but for a tuple or perhaps even a list (mutability might be a problem there), I can't see why it wouldn't be possible.

任何人都知道如果是否有可能从itertools.cycle实例中提取非无限迭代.如果不是,那么有人知道为什么这个主意不好吗?

Anyone know if its possible to extract the non-infinite iterable out of an itertools.cycle instance. If not, anybody know why this idea is a bad one?

推荐答案

这是不可能的.如果查看itertools.cycle代码,您会发现它没有存储序列的副本.它仅创建一个可迭代对象,并将可迭代对象中包含的值存储在新创建的列表中:

It's impossible. If you look at itertools.cycle code you'll see that it does not store a copy of the sequence. It only create an iterable and store the values contained in the iterable in a newly created list:

static PyObject *
cycle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    PyObject *it;
    PyObject *iterable;
    PyObject *saved;
    cycleobject *lz;

    if (type == &cycle_type && !_PyArg_NoKeywords("cycle()", kwds))
        return NULL;

    if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable))
        return NULL;
    /* NOTE: they do not store the *sequence*, only the iterator */
    /* Get iterator. */
    it = PyObject_GetIter(iterable);
    if (it == NULL)
        return NULL;

    saved = PyList_New(0);
    if (saved == NULL) {
        Py_DECREF(it);
        return NULL;
    }

    /* create cycleobject structure */
    lz = (cycleobject *)type->tp_alloc(type, 0);
    if (lz == NULL) {
        Py_DECREF(it);
        Py_DECREF(saved);
        return NULL;
    }
    lz->it = it;
    lz->saved = saved;
    lz->firstpass = 0;

    return (PyObject *)lz;
}

这意味着在执行以下操作:

This means that when doing:

itertools.cycle([1,2,3])

您创建的列表只有1个引用,该引用保存在cycle所使用的迭代器中. 当迭代器用尽时,迭代器将被删除并创建一个新的迭代器:

The list you create has only 1 reference, that is kept in the iterator used by cycle. When the iterator is exhausted the iterator gets deleted and a new iterator is created:

    /* taken from the "cycle.next" implementation */
    it = PyObject_GetIter(lz->saved);
    if (it == NULL)
        return NULL;
    tmp = lz->it;
    lz->it = it;
    lz->firstpass = 1;
    Py_DECREF(tmp);   /* destroys the old iterator */

这意味着经过一个周期后,列表被销毁了.

Which means that after doing one cycle the list is destroyed.

无论如何,如果您需要访问此列表,只需在调用itertools.cycle之前在某处引用它即可.

Anyway if you need access to this list, just reference it somewhere before calling itertools.cycle.

这篇关于从itertools.cycle中提取列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆