根据输入在Python中产生元组或命名元组

时间:2016-05-16 19:45:32

标签: python-2.7 tuples namedtuple

在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的额外检查。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

我更多地研究了这个,并且namedTuple确实有一个_make()方法,它接受一个iterable并创建一个namedtuple,所以第一个yield语句可以是:

yield iterType._make(map(next, cycles))

取消星号,但当然listtuple没有_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(...)