Python 如何在列表中执行多个操作

Python 如何在列表中执行多个操作,python,list,operation,Python,List,Operation,如何让它在(0,50)之间选择5个随机数,然后在(0,12)之间选择2个随机数?不要重复使用名称列表。一种方法是循环遍历边界的一个iterable,并将其发送到randint L = [random.randint(0,50) for i in range(5) random.randint(0,12) for i in range(2)] 您还可以使用itertools.chain和itertools.repeat来避免构建边界列表 from random import randint l

如何让它在(0,50)之间选择5个随机数,然后在(0,12)之间选择2个随机数?

不要重复使用名称
列表。一种方法是循环遍历边界的一个iterable,并将其发送到
randint

L = [random.randint(0,50) for i in range(5) random.randint(0,12) for i in range(2)]
您还可以使用
itertools.chain
itertools.repeat
来避免构建边界列表

from random import randint

lst = [randint(*bounds) for bounds in [(0, 50)]*5 + [(0, 12)]*2]

您可以根据
i
的值将第二个参数更改为
randint()

lst = [randint(*bounds) for bounds in chain(repeat((0, 50), 5), repeat((0, 12), 2))]
可能性是无穷的。Lambdas,
randint(0,上限)
randint(*args)
,这是一个函数,它的结果会根据调用频率的不同而变化,等等。但我不认为这些函数实际上更可读或更容易理解

对于本例,仅使用7个值,我将连接两个列表:

from functools import partial
from random import randint

rint50 = partial(randint, 0, 50)
rint12 = partial(randint, 0, 12)
[rint() for rint in [rint50] * 5 + [rint12] * 2]

因为它更干净,可读性更强。创建包含两个列表理解结果的第三个列表的性能成本很小,在这里可以忽略不计。

类似于这样的东西,连接两个列表:

[randint(0, 50) for _ in range(5)] + [randint(0, 12) for _ in range(2)]
import random
l = [random.randint(0,50) for i in range(5)]
l.extend([random.randint(0,12) for i in range(2)])

print(l)

如果您乐于使用第三方库,您可以通过NumPy:

from random import randint
my_list = [randint(0,50) for i in range(5)] + [randint(0,12) for i in range(2)]
这种方法的好处,即内存预分配,将在较大的阵列中体现出来

import numpy as np

np.random.seed(0) # for consistency / testing

A = np.zeros(7)
A[:5] = np.random.randint(0, 20, 5)
A[5:] = np.random.randint(0, 12, 2)

array([ 12.,  15.,   0.,   3.,   3.,   7.,   9.])

lst=[random.randint(0,50),如果i<5,则为random.randint(0,12),表示范围(7)内的i]
打印(lst)#[7,10,40,4,38,1,5]
您可以使用列表理解和内置功能来完成此操作,一些怪物如:

lst = [random.randint(0,50) if i < 5 else random.randint(0,12) for i in range(7)]

print(lst) # [7, 10, 40, 4, 38, 1, 5]
也许,如果您想使用itertools,可以执行以下操作:

>>> result = [
...     random.randint(a,b)
...     for args in (((0,50) for _ in range(5)), ((0, 12) for _ in range(2)))
...     for a, b in args
... ]
>>> result
[33, 38, 19, 9, 47, 0, 8]

这两种方法都难以理解和简单。相反,我个人会选择两个for循环,一种幼稚的方法。它将是高效、简单和可读的。除了展示之外,我认为上述方法在生产代码中没有任何优势。

这里有另一个变体,可以避免在每次迭代中进行
if
测试。它还使用
randrange
,这比
randint
的效率略高

>>> from itertools import chain, repeat, starmap
>>> list(starmap(random.randint, chain(repeat((0,50),5), repeat((0,12),2))))
[16, 47, 40, 21, 15, 12, 4]
典型输出

from random import randrange
lst = [randrange(hi) for num, hi in ((5, 51), (2, 13)) for _ in range(num)]
print(lst)
from timeit import Timer
import random
from random import randint, randrange, seed
from itertools import chain, repeat, starmap
from functools import partial
import numpy as np

imports = 'random, randint, randrange, seed, chain, repeat, starmap, partial, np'

commands = (
    ('Martijn', '', '[randint(0, 50 if i < 5 else 12) for i in range(7)]'),
    ('Martijn_partial', 
        'rint50 = partial(randint, 0, 50); rint12 = partial(randint, 0, 12)', 
        '[rint() for rint in [rint50] * 5 + [rint12] * 2]'
    ),
    ('Patrick', '', '[randint(*bounds) for bounds in [(0, 50)]*5 + [(0, 12)]*2]'),
    ('Patrick_chain', '', 
        '[randint(*bounds) for bounds in chain(repeat((0, 50), 5), repeat((0, 12), 2))]'
    ),
    ('Ralf', '', '[randint(0,50) for i in range(5)] + [randint(0,12) for i in range(2)]'),
    ('Abhishek', '', 'l = [random.randint(0,50) for i in range(5)];'
        'l.extend([random.randint(0,12) for i in range(2)])'
    ),
    ('PM 2Ring', '', '[randrange(hi) for num, hi in ((5, 51), (2, 13)) for _ in range(num)]'),
    ('jpp', '', 'A = np.zeros(7); ' 
        'A[:5] = np.random.randint(0, 20, 5); A[5:] = np.random.randint(0, 12, 2)'
    ),
    ('Tanmay jain', '', 
        '[random.randint(0,50) if i < 5 else random.randint(0,12) for i in range(7)]'
    ),
    ('juanpa', '', '[random.randint(a,b) for args in (((0,50) for _ in range(5)),' 
        '((0, 12) for _ in range(2))) for a, b in args]'
    ),
    ('juanpa_starmap', '', 'list(starmap(random.randint,'
        'chain(repeat((0,50),5), repeat((0,12),2))))'
    ),
)

def verify():
    for name, setup, cmd in commands:
        if name in ('jpp', 'Abhishek'):
            continue
        seed(17)
        if setup:
            exec(setup)
        print('{:16}: {}'.format(name, eval(cmd)))
    print()

def time_test(loops):
    timings = []
    print('loops =', loops)
    for name, setup, cmd in commands:
        setup = 'from __main__ import ' + imports + ';' + setup
        t = Timer(cmd, setup=setup)
        result = sorted(t.repeat(3, loops))
        timings.append((result, name))
    timings.sort()
    for result, name in timings:
        print('{:16} : {}'.format(name, result))

verify()
time_test(5000)
这相当于

[10, 31, 46, 25, 23, 6, 5]
外部循环选择
num
、子列表中的项目数和该子列表的
hi
随机范围的大小;内部循环在所需范围内生成所需数量的随机数


FWIW,这里有一些代码比较已经提交的各种算法。它还验证了当给定相同的随机种子时,它们产生相同的结果。我的简单验证代码使用了
eval
,所以它只能测试表达式,不能测试语句,所以它不能测试jpp或Abhishek的代码;此外,jpp的Numpy代码给出了不同的结果,因为它使用了不同的种子算法。请参阅
timeit
文档,了解
timeit
的功能以及如何解释结果

lst = []
for num, hi in ((5, 51), (2, 13)):
    for _ in range(num):
        lst.append(randrange(hi))
正如您所看到的,jpp的Numpy代码是最快的。我预计,如果我们生成更长的数字列表,速度差异将更加明显

这些计时是在一台古老的32位单核2GHz机器上执行的,该机器在Debian派生发行版上运行Python 3.6.0。YMMV


以下是在相同范围内生成50+20=70个值的列表(或数组)的计时

Martijn         : [33, 26, 19, 23, 18, 2, 12]
Martijn_partial : [33, 26, 19, 23, 18, 2, 12]
Patrick         : [33, 26, 19, 23, 18, 2, 12]
Patrick_chain   : [33, 26, 19, 23, 18, 2, 12]
Ralf            : [33, 26, 19, 23, 18, 2, 12]
PM 2Ring        : [33, 26, 19, 23, 18, 2, 12]
Tanmay jain     : [33, 26, 19, 23, 18, 2, 12]
juanpa          : [33, 26, 19, 23, 18, 2, 12]
juanpa_starmap  : [33, 26, 19, 23, 18, 2, 12]

loops = 5000
jpp              : [0.23938178099342622, 0.24184146700281417, 0.3152835669970955]
PM 2Ring         : [0.26918871099769603, 0.27244400099880295, 0.2916741489971173]
Patrick          : [0.34155847399961203, 0.34415175200410886, 0.3531294650019845]
juanpa_starmap   : [0.3417540490045212, 0.34329504700144753, 0.3438059809996048]
Martijn          : [0.3509639670010074, 0.362117896998825, 0.547288200003095]
Martijn_partial  : [0.3511254819968599, 0.35262946599686984, 0.39430355399963446]
Patrick_chain    : [0.3541102219969616, 0.3545923809942906, 0.3555165420038975]
Tanmay jain      : [0.3558294050017139, 0.5510739650053438, 0.7693202439986635]
Ralf             : [0.3678122450000956, 0.44522786799643654, 0.44827762299973983]
juanpa           : [0.4089203829935286, 0.41227930299646687, 0.42410747800022364]
Abhishek         : [0.4811078249986167, 0.4942625819967361, 0.6255962599971099]

你想要的产量是多少?不要给你的列表命名
list
list理解只适用于构建列表的循环。如果您可以在常规的
for
循环中使用
列表。附加(…)
部分来表达您的需求,那么您可能也可以将其作为列表理解。它在这里只是命名列表,而不是在我的实际代码中。我想要的结果是一个由7个随机数组成的列表,其中5个从(0,50)范围内选取,2个从(0,12)范围内选取。您可能对我添加到答案中的
timeit
结果感兴趣。完美的人,谢谢!我一定是在沮丧中错过了!美好的我想我唯一不喜欢列表理解的地方就是可读性。@artomason:那取决于你是如何使用它们的。在这里,表达式很容易太难看。对于7个值,比较计时几乎没有意义。从性能的角度来看这确实是一个过早的优化。
from timeit import Timer
import random
from random import randint, randrange, seed
from itertools import chain, repeat, starmap
from functools import partial
import numpy as np

imports = 'random, randint, randrange, seed, chain, repeat, starmap, partial, np'

commands = (
    ('Martijn', '', '[randint(0, 50 if i < 5 else 12) for i in range(7)]'),
    ('Martijn_partial', 
        'rint50 = partial(randint, 0, 50); rint12 = partial(randint, 0, 12)', 
        '[rint() for rint in [rint50] * 5 + [rint12] * 2]'
    ),
    ('Patrick', '', '[randint(*bounds) for bounds in [(0, 50)]*5 + [(0, 12)]*2]'),
    ('Patrick_chain', '', 
        '[randint(*bounds) for bounds in chain(repeat((0, 50), 5), repeat((0, 12), 2))]'
    ),
    ('Ralf', '', '[randint(0,50) for i in range(5)] + [randint(0,12) for i in range(2)]'),
    ('Abhishek', '', 'l = [random.randint(0,50) for i in range(5)];'
        'l.extend([random.randint(0,12) for i in range(2)])'
    ),
    ('PM 2Ring', '', '[randrange(hi) for num, hi in ((5, 51), (2, 13)) for _ in range(num)]'),
    ('jpp', '', 'A = np.zeros(7); ' 
        'A[:5] = np.random.randint(0, 20, 5); A[5:] = np.random.randint(0, 12, 2)'
    ),
    ('Tanmay jain', '', 
        '[random.randint(0,50) if i < 5 else random.randint(0,12) for i in range(7)]'
    ),
    ('juanpa', '', '[random.randint(a,b) for args in (((0,50) for _ in range(5)),' 
        '((0, 12) for _ in range(2))) for a, b in args]'
    ),
    ('juanpa_starmap', '', 'list(starmap(random.randint,'
        'chain(repeat((0,50),5), repeat((0,12),2))))'
    ),
)

def verify():
    for name, setup, cmd in commands:
        if name in ('jpp', 'Abhishek'):
            continue
        seed(17)
        if setup:
            exec(setup)
        print('{:16}: {}'.format(name, eval(cmd)))
    print()

def time_test(loops):
    timings = []
    print('loops =', loops)
    for name, setup, cmd in commands:
        setup = 'from __main__ import ' + imports + ';' + setup
        t = Timer(cmd, setup=setup)
        result = sorted(t.repeat(3, loops))
        timings.append((result, name))
    timings.sort()
    for result, name in timings:
        print('{:16} : {}'.format(name, result))

verify()
time_test(5000)
Martijn         : [33, 26, 19, 23, 18, 2, 12]
Martijn_partial : [33, 26, 19, 23, 18, 2, 12]
Patrick         : [33, 26, 19, 23, 18, 2, 12]
Patrick_chain   : [33, 26, 19, 23, 18, 2, 12]
Ralf            : [33, 26, 19, 23, 18, 2, 12]
PM 2Ring        : [33, 26, 19, 23, 18, 2, 12]
Tanmay jain     : [33, 26, 19, 23, 18, 2, 12]
juanpa          : [33, 26, 19, 23, 18, 2, 12]
juanpa_starmap  : [33, 26, 19, 23, 18, 2, 12]

loops = 5000
jpp              : [0.23938178099342622, 0.24184146700281417, 0.3152835669970955]
PM 2Ring         : [0.26918871099769603, 0.27244400099880295, 0.2916741489971173]
Patrick          : [0.34155847399961203, 0.34415175200410886, 0.3531294650019845]
juanpa_starmap   : [0.3417540490045212, 0.34329504700144753, 0.3438059809996048]
Martijn          : [0.3509639670010074, 0.362117896998825, 0.547288200003095]
Martijn_partial  : [0.3511254819968599, 0.35262946599686984, 0.39430355399963446]
Patrick_chain    : [0.3541102219969616, 0.3545923809942906, 0.3555165420038975]
Tanmay jain      : [0.3558294050017139, 0.5510739650053438, 0.7693202439986635]
Ralf             : [0.3678122450000956, 0.44522786799643654, 0.44827762299973983]
juanpa           : [0.4089203829935286, 0.41227930299646687, 0.42410747800022364]
Abhishek         : [0.4811078249986167, 0.4942625819967361, 0.6255962599971099]
loops = 500
jpp              : [0.025625186994147953, 0.025764200996491127, 0.03122780400008196]
PM 2Ring         : [0.21989007600495825, 0.2200367909972556, 0.22065802400175016]
juanpa_starmap   : [0.3094131350007956, 0.3110805670003174, 0.31563361900043674]
Patrick_chain    : [0.3122365829985938, 0.31262181099737063, 0.3137894630053779]
Patrick          : [0.3130071220002719, 0.31769691400404554, 0.3179219129960984]
Ralf             : [0.31566168300196296, 0.3157304769993061, 0.3234770689959987]
Martijn          : [0.3193310350034153, 0.3275600470005884, 0.35491854500287445]
Martijn_partial  : [0.321399387998099, 0.3226969290044508, 0.32442738999816356]
Abhishek         : [0.32655813400197076, 0.3363869300010265, 0.3657162370000151]
Tanmay jain      : [0.32833286200184375, 0.33107244400162017, 0.39565577400207985]
juanpa           : [0.35968791200139094, 0.3754627199959941, 0.3933205349967466]