1

我想知道是否有办法重构以下代码

 first_run = True
 for i in gen:
        if first_run:
            last_head = i[1]
            last_tail = i[2]
            last_chrom = i[0]
            first_run = False
        else:
            func(i[1], last_head)
            func(i[1], last_tail)
            last_head = i[1]
            last_tail = i[2]
            last_chrom = i[0]
4

6 回答 6

5

循环的要点似乎是对可迭代的连续元素对执行一些操作。因此,我会查看模块文档pairwise中给出其定义的函数:itertools

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

请注意,这不是实际itertools功能,您必须将实现复制并粘贴到您的代码中。无论如何,有了这个函数,你的循环可以像这样实现:

for a, b in pairwise(gen):
    func(b[1], a[1])
    func(b[1], a[2])
于 2012-10-30T08:33:12.697 回答
1

这应该简化循环

first_run = True
for i in gen:
    if first_run == False:
        func(i[1], last_head)
        func(i[1], last_tail)

     last_head, last_tail, last_chrom  = i[1], i[2], i[0]
     first_run = False

更新了答案...

于 2012-10-30T07:48:13.423 回答
1

我会删除if / else并通过切片列表分配 - 除非func的参数是由它更新的对象:如果 gen 是生成器:

my_gen = gen
values = my_gen.next()
last_chrom, last_head, last_tail = values[:3]
for values in my_gen:
    func(last_head, last_head)
    func(last_head, last_tail)
    last_chrom, last_head, last_tail = values[:3]

编辑:刚刚注意到我的错误

于 2012-10-30T07:57:14.950 回答
0

如果您在循环后不需要变量 last_head、last_tail 和 last_chrom,则可以采用以下解决方案:

for index, val in enumerate(gen[:1]):
    func(val[1], gen[index-1][1])
    func(val[1], gen[index-1][2])
于 2012-10-30T07:57:23.010 回答
0

我最喜欢以特殊方式处理“第一项”的方法是一次性循环break

def gen():
    for x in range(5):
        yield x

def first_special(g):
    for item in g:
        print 'first', item
        break
    for item in g:
        print item

 first_special(gen())
 # prints "first 0, 1,2,3,4

请注意,这适用于单元素或空迭代器。为了也first_special可以使用任意迭代,我通常会iter()向它添加一个安全调用:

def first_special(g):
    g = iter(g)
    for item in g:
        print 'first', item
        break
    for item in g:
        print item
于 2012-10-30T09:43:24.173 回答
0
it = iter(gen) # make sure we have an iterator
_, last_head, last_tail = next(it, [None]*3) # assume iterator returns 3 values
for _, head, tail in it:
    func(head, last_head)
    func(head, last_tail)
    last_head, last_tail = head, tail

如果您不能假设迭代器一次返回 3 个值,那么:

it = iter(gen)
last = next(it, None)
for x in it:
    func(x[1], last[1]) # head, last_head
    func(x[1], last[2]) # head, last_tail
    last = x

您还可以使用@David建议的itertools'pairwise()食谱:

for last, x in pairwise(gen):
    func(x[1], last[1]) # head, last_head
    func(x[1], last[2]) # head, last_tail
于 2012-10-30T08:46:16.217 回答