【发布时间】:2016-07-13 23:24:39
【问题描述】:
我想创建一个迭代器,它有多个对象“源”进行迭代。我希望能够为其__next__() 方法提供一个可选的关键字参数,以提供选择源的可能性(没有关键字参数意味着,只需随机选择一个源)。
使用__next__() 会导致问题(见下文),因此作为一种解决方法,我编写了这个不令人满意的代码:
#!/usr/bin/env python3
import random
class infinite_iterator(object):
def __init__(self, sources):
self.collector = []
for s in sources:
random.shuffle(s)
self.collector.append([])
self.sources = sources
def __iter__(self):
return self
# Workaround: calling it next instead of __next__
# (not the python3 way...)
def next(self, **kwargs):
sce_nb = random.choice([ n for n in range(len(self.sources)) ])
if 'choice' in kwargs:
sce_nb = kwargs['choice']
self.collector[sce_nb].append(self.sources[sce_nb][0])
output = self.sources[sce_nb].pop(0)
# Repopulate any empty 'source'
if not self.sources[sce_nb]:
(self.sources[sce_nb], self.collector[sce_nb]) = \
(self.collector[sce_nb], self.sources[sce_nb])
random.shuffle(self.sources[sce_nb])
return output
S = infinite_iterator([["Adam", "Paul", "Oliver", "Aaron", "Joshua", "Jack"],
["Mary", "Sophia", "Emily", "Isobel", "Grace", "Alice", "Lucy"]])
print("Any name: " + S.next())
print("Any girl's name: " + S.next(choice=1))
print("Any boy's name: " + S.next(choice=0))
问题是,如果我想写def __next__(self, **kwargs): 让infinite_iterator 成为真正的Iterator,那我当然想写:
print("Any name: " + next(S))
print("Any girl's name: " + next(S, choice=1))
print("Any boy's name: " + next(S, choice=0))
但出现错误(2d 行):
TypeError: next() takes no keyword arguments
我认为这个调用next(S, choice=1) 会使用对象中定义的__next__() 函数。由于这个错误,我认为一方面它实际上没有。这可能是可以预料的,因为它不完全是重新定义,因为infinite_iterator 不继承自“迭代器对象”(据我所知,没有这样的对象)。但另一方面,如果我只调用 next(S) 它可以工作,在这种情况下,my __next__() 方法确实被调用(它随机选择一个列表进行迭代)。
最后,有没有办法实现这样的Iterator?
【问题讨论】:
标签: python python-3.x iterator next redefinition