我是一个非常新手的程序员。我正在尝试使用combinations
模块中的itertools
工具。所以我试试:
from itertools import *
print combinations('12345', 3)
但不是预期的('123', '124', '125', [...])
,而是<itertools.combinations object at [pointer]>
。我很困惑,因为在其他模块中调用方法会返回预期的结果,例如:
import random
print random.randrange(10)
>>> 9
我对itertools模块做错了什么?
答案 0 :(得分:6)
无。结果就是它应该是什么。您显然没有考虑的是结果是迭代器,而不是完全评估的结果列表/元组。您看到的输出是该对象的repr()
(它是不>返回一个字符串)。您可以通过将前者传递给list
构造函数来将前者转换为后者:
import itertools
print list(itertools.combinations('12345', 3))
但是当你不需要它而你只是遍历值时,它会通过不同时存储所有结果来节省大量内存。它还允许通过不消耗整个迭代器来避免工作(例如,找到满足某些条件然后返回的第一个组合)。
答案 1 :(得分:3)
itertools.combinations
返回一个iterable(您可以在Python文档中的equivalent codes中看到yield
关键字的使用)。如果要打印完整序列,可以使用list(combinations(...))
。
>>> print list(combinations('12345', 3))
[('1', '2', '3'), ('1', '2', '4'), ('1', '2', '5'), ('1', '3', '4'), ('1', '3', '5' ('2', '3', '5'), ('2', '4', '5'), ('3', '4', '5')]
答案 2 :(得分:2)
这是一个迭代器。您可以使用list
或tuple
将其转换为list(combinations('12345', 3))
或tuple(combinations('12345', 3))
。
根据你的问题我认为你可能会对序列,迭代和迭代器有什么困惑。我认为完全理解它们以便能够编写和/或理解python代码是有用的,所以我会尝试给你一个关于这个问题的解释。
list
和tuple
个对象是序列。序列是支持某些特定操作的对象。即他们是 iterables (你可以做for elem in sequence
),他们支持“项目访问”(sequence[key]
有效)他们有“长度”(len(sequence)
是有效),您可以检查项目是否在序列中(elem in sequence
有效)。
[有complete list个操作构成“序列协议”。唉它特定于C-API。然而,这些函数的名称和解释应该让您了解它们支持的整套操作]
在python中还有另外两种对象,在某些情况下可以使用而不是序列: iterables 和 iterators 。
iterable是一个支持迭代的对象。说到python,如果对象具有返回迭代器的__iter__
方法,则该对象是可迭代的。
迭代器是一个在一个iterable上迭代一次并逐个产生值的对象。在python中,迭代器是一个实现__iter__
和__next__
方法(python2中的next
)的对象。 __iter__
通常“什么都不做”,只返回对象本身。 next
方法返回iterable中的下一个值。
现在,combinations('12345', 3)
是一个可迭代的,这意味着您可以循环使用它,但是您无法使用iterable[key]
语法访问它的项目,并且您无法使用len
获取其长度。
为什么要使用迭代器?在某些情况下,您可以避免将一整个值序列放入内存中进行迭代。例如,如果您想将数字1
循环到100
,则无需创建填充数字的list
长度100
并迭代它。提供一个值,您可以计算下一个添加1
。
因此,基本上迭代是一种减少内存使用的方法,并且通常是“循环某事”所需功能的抽象。如果你想要一个序列,你可以按照前面的说明进行转换。
一种特殊的迭代器是所谓的生成器。生成器只是可以使用函数语法编写的迭代器,特别是它们使用yield
关键字:
>>> def numbers(n):
... while n > 0:
... yield n
... n -= 1
...
>>> numbers(5)
<generator object numbers at 0xb744a93c>
>>> for elem in numbers(5):
... print elem
...
5
4
3
2
1
正如您在致电numbers
时所看到的那样,代码是而不是执行。相反,python创建了一个生成器对象,它是一个迭代器。迭代对象时,函数内的代码将被执行,直到遇到yield
为止。发生这种情况时,将返回yield
的“参数”并冻结执行。当新的迭代开始时,它会重新开始。
在这个例子中,你可以更好地看到执行流程:
>>> def flow():
... yield 'Execution stopped here'
... yield 'Execution continues'
... yield 'Execution ended'
...
>>> generator = flow()
>>> next(generator) #same as generator.__next__()
'Execution stopped here'
>>> next(generator)
'Execution continues'
>>> next(generator)
'Execution ended'
>>> next(generator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
您可能有兴趣阅读其中提出的PEP255。实际上它们已被扩展为提供协程功能,但我认为现在已经足够了。
答案 3 :(得分:0)
itertools.combination
是一个班级;因此,调用itertools.combinations()
返回该实例的实例,该实例可以迭代以获取值:
for combo in combinations('12345', 3):
print combo