Python 使用此setitem函数来克服列表理解限制是否会非常不和谐?

Python 使用此setitem函数来克服列表理解限制是否会非常不和谐?,python,variable-assignment,list-comprehension,side-effects,Python,Variable Assignment,List Comprehension,Side Effects,不要使用列表理解来执行副作用-这不是Pythonic。改为使用显式循环: >>> a=range(5) >>> [a[i] for i in range(0,len(a),2)] ## list comprehension for side effects [0, 2, 4] >>> a [0, 1, 2, 3, 4] >>> [a[i]=3 for i in range(0,len(a),2)] ## try to do

不要使用列表理解来执行副作用-这不是Pythonic。改为使用显式循环:

>>> a=range(5)
>>> [a[i] for i in range(0,len(a),2)] ## list comprehension for side effects
[0, 2, 4]
>>> a
[0, 1, 2, 3, 4]
>>> [a[i]=3 for i in range(0,len(a),2)] ## try to do assignment
SyntaxError: invalid syntax
>>> def setitem(listtochange,n,value):  ## function to overcome limitation
    listtochange[n]=value
    return value

>>> [setitem(a,i,'x') for i in range(0,len(a),2)] ## proving the function
['x', 'x', 'x']
>>> a 
['x', 1, 'x', 3, 'x']   # We did assignment anyway

除了列表理解中令人惊讶和意外的副作用外,您正在构建一个从未使用过的结果列表,这在这里是浪费和完全不必要的。

是的。我建议使用

for i in range(0,len(a),2):
    a[i] = 3
相反


编辑:

Python 2.6的微基准:

a[::2] = ['x'] * len(a[::2])
Python 3.1:

~:249$ python2.6 -m timeit -s 'a = range(2000)' 'a[::2] = [8] * len(a[::2])'
10000 loops, best of 3: 26.2 usec per loop

~:250$ python2.6 -m timeit -s 'a = range(2000)' 'a[::2] = [8] * (len(a)/2)'
10000 loops, best of 3: 19.6 usec per loop

~:251$ python2.6 -m timeit -s 'a = range(2000)' 'for i in xrange(0,len(a),2): a[i] = 8'
10000 loops, best of 3: 92.1 usec per loop

~:252$ python2.6 -m timeit -s 'a = range(2000)
> def assign(x,i,v):x[i]=v;return v' '[assign(a,i,8) for i in xrange(0, len(a), 2)]'
1000 loops, best of 3: 336 usec per loop

您也可以使用
list.\uuuuu setitem\uuuuuuu

~:253$ python3.1 -m timeit -s 'a = list(range(2000))' 'a[::2] = [8] * len(a[::2])'
100000 loops, best of 3: 19.8 usec per loop

~:254$ python3.1 -m timeit -s 'a = list(range(2000))' 'a[::2] = [8] * (len(a)//2)'
100000 loops, best of 3: 13.4 usec per loop

~:255$ python3.1 -m timeit -s 'a = list(range(2000))' 'for i in range(0,len(a),2): a[i] = 8'
10000 loops, best of 3: 119 usec per loop

~:256$ python3.1 -m timeit -s 'a = list(range(2000))
> def assign(x,i,v):x[i]=v;return v' '[assign(a,i,8) for i in range(0, len(a), 2)]'
1000 loops, best of 3: 361 usec per loop
或者,如果您希望避免构建中间列表:

a = range(5)
[a.__setitem__(i,"x") for i in range(0,len(a),2)]
但列表理解中的赋值确实是非语法的

关于我提到的时间安排(另请参见) 从时间输入时钟

any(a.__setitem__(i,"x") for i in range(0,len(a),2))
def rwh_primes1(n):
# https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
“”“返回素数列表
长度函数和带setitem的所有函数都不是令人满意的备选方案,但这里的计时就是为了证明这一点

rwh筛,具有len功能 长度78498,257.80008353毫秒

rwh筛有任何副作用
长度为78498,829.977273648 ms

我希望我能不止一次地更新这个。不要调用你的函数
set
。我不得不说,即使在你评论说Python中有set,甚至不像Lisp中的函数。至于副作用,我知道它们并不总是受欢迎,但有时非常有用。例如,我认为这段代码很漂亮:如果没有使用值,就可以解决每个数独难题,目的很明确。请参阅我在筛优化上的另一篇文章,再生和len太贵了。如果您需要,我可以通过简单的time.clock()计时来给您计时结果。感谢您提供的数据,我更正了问题中的函数名,使其与此私有函数名相对应。您的编辑有点忽略了点--list.。\uuuuu setitem\uuuuuuuuuuuuuuuuu是一个内置函数,这意味着您不必自己定义它;它会自动包含在所有的列表中。时间比较见下面的帖子,可惜不是很好。我需要取出这个集合作为名称,因为它是内置的,而且setitem是私有的,所以可以只使用“setitem”。
def rwh_primes1(n):
    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Returns  a list of primes < n """
    sieve = [True] * (n//2)
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
    return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]

def rwh_primes_tjv(n):
    # recurrence formula for length by amount1 and amount2 tjv
    """ Returns  a list of primes < n """
    sieve = [True] * (n//2)
    amount1 = n-10
    amount2 = 6

    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
             ## can you make recurrence formula for whole reciprocal?
            sieve[i*i//2::i] = [False] * (amount1//amount2+1)
        amount1-=4*i+4
        amount2+=4

    return [2] + [2*i+1 for i in xrange(1,n//2) if sieve[i]]

def rwh_primes_len(n):
    """ Returns  a list of primes < n """
    sieve = [True] * (n//2)

    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * len(sieve[i*i//2::i])

    return [2] + [2*i+1 for i in xrange(1,n//2) if sieve[i]]

def rwh_primes_any(n):
    """ Returns  a list of primes < n """
    halfn=n//2
    sieve = [True] * (halfn)

    for i in range(3,int(n**0.5)+1,2):
        if sieve[i//2]:
            any(sieve.__setitem__(item,False) for item in range(i*i//2,halfn,i))

    return [2] + [2*i+1 for i in xrange(1,n//2) if sieve[i]]


if __name__ == "__main__":
    n = 1000000

    print("rwh sieve1")
    t=clock()
    r=rwh_primes1(n)
    print("Length %i,  %s ms" %(len(r),1000*(clock()-t)))

    print("rwh sieve with recurrence formula")
    t=clock()
    r=rwh_primes_tjv(n)
    print("Length %i,  %s ms" %(len(r),1000*(clock()-t)))

    print("rwh sieve with len function")
    t=clock()
    r=rwh_primes_len(n)
    print("Length %i,  %s ms" %(len(r),1000*(clock()-t)))

    print("rwh sieve with any with side effects")
    t=clock()
    r=rwh_primes_any(n)
    print("Length %i,  %s ms" %(len(r),1000*(clock()-t)))
    raw_input('Ready')

""" Output:
rwh sieve1
Length 78498,  213.199442946 ms
rwh sieve with recurrence formula
Length 78498,  218.34143725 ms
rwh sieve with len function
Length 78498,  257.80008353 ms
rwh sieve with any with side effects
Length 78498,  829.977273648 ms
Ready
"""