在Python 2.7中,我有一个函数,它接受一个迭代元组,将每个迭代映射到itertools.cycle,然后不断产生新的元组。与zip类似,但它会重新启动每个迭代而不是停止。一切都很好,直到Raymond Hettinger说服我使用更多的命名元组。我转换了我的函数,但我无法找出处理元组和命名元组的最佳方法。问题是,在初始化时,namedtuple需要各个参数,但是元组需要一个可迭代的。
NT = namedtuple('NT', ['X', 'Y', 'Z'])
x = [1,2]
y = ['a','b','c']
z = ['V','W','X','Y','Z']
def var_gen(inputLists):
tupleType = type(inputLists)
cycles = map(itertools.cycle, inputLists)
while 1:
if tupleType is tuple:
# No asterisk for tuple
yield tuple(map(next, cycles))
else:
# With asterisk for namedtuple
yield tupleType(*map(next, cycles))
gen = var_gen(NT(x,y,z))
for i in xrange(10):
print next(gen)
上面的代码适用于元组和命名元组,但它不适合鸭子打字,它会为每个产量创建一个额外的检查,感觉需要检查一些代码味道和两条相同的行除了一个星号。我的实际函数在while循环中有一些额外的代码,所以我不想通过创建两个单独的while循环来删除每个yield的额外检查。
感谢您的帮助。
答案 0 :(得分:1)
我更多地研究了这个,并且namedTuple确实有一个_make()
方法,它接受一个iterable并创建一个namedtuple,所以第一个yield语句可以是:
yield iterType._make(map(next, cycles))
取消星号,但当然list
和tuple
没有_make()
方法,因此您仍然需要额外的一行。我无法从source code中找出为什么难以允许MY_NAMED_TUPLE([iterable])
,但必须有某种原因。
这是我可以开发的最佳解决方案。它只修复我的鸭子输入投诉,但它确实处理列表,元组,命名元组和生成器。
NT = namedtuple('NT', 'X Y Z')
NT_One = namedtuple('NT_One', 'Only')
x = [1,2]
y = ['a','b','c']
z = ['V','W','X','Y','Z']
def var_gen(inputLists):
if iter(inputLists) is iter(inputLists):
# Tests if inputLists is a generator
iterType = tuple
else:
iterType = type(inputLists)
cycles = map(itertools.cycle, inputLists)
while 1:
try:
# This is the logic for a named tuple
yield iterType(*map(next, cycles))
except Exception:
yield iterType(map(next, cycles))
test = []
test.append(var_gen(NT(x,y,z))) # namedtuple with multiple fields
test.append(var_gen(NT_One(x))) # namedtuple with only one field
test.append(var_gen((x,y,z))) # regular tuple
test.append(var_gen([x,y,z])) # list
test.append(var_gen((i for i in (x,y,z)))) # generator
for gen in test:
print 'Next Test:'
for i in xrange(10):
print next(gen)
print ' '
答案 1 :(得分:0)
你的程序的单次运行是完全与其中一个完全相同吗?如果是这样,这样的模式可能会有用:
def var_gen_tuple():
...
def var_gen_namedtuple():
...
var_gen = var_gen_namedtuple
if tupleType is tuple:
var_gen = var_gen_tuple
var_gen(...)