Yux*_*ang 62 python performance python-2.7 python-3.x
在固体力学中,我经常使用Python并编写如下所示的代码:
for i in range(3):
for j in range(3):
for k in range(3):
for l in range(3):
# do stuff
Run Code Online (Sandbox Code Playgroud)
我经常这样做,我开始怀疑是否有更简洁的方法来做到这一点.当前代码的缺点是:如果我遵守PEP8,那么我不能超过每行79个字符的限制,并且没有太多的空间,特别是如果这又是一个类的功能.
Kas*_*mvd 120
根据你想要做的事情,你可以使用itertools模块来最小化for循环(或zip).在这种情况下itertools.product,你将创建你用4循环完成的工作:
>>> list(product(range(3),repeat=4))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 1, 0), (0, 0, 1, 1),
(0, 0, 1, 2), (0, 0, 2, 0), (0, 0, 2, 1), (0, 0, 2, 2), (0, 1, 0, 0),
(0, 1, 0, 1), (0, 1, 0, 2), (0, 1, 1, 0), (0, 1, 1, 1), (0, 1, 1, 2),
(0, 1, 2, 0), (0, 1, 2, 1), (0, 1, 2, 2), (0, 2, 0, 0), (0, 2, 0, 1),
(0, 2, 0, 2), (0, 2, 1, 0), (0, 2, 1, 1), (0, 2, 1, 2), (0, 2, 2, 0),
(0, 2, 2, 1), (0, 2, 2, 2), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 0, 2),
(1, 0, 1, 0), (1, 0, 1, 1), (1, 0, 1, 2), (1, 0, 2, 0), (1, 0, 2, 1),
(1, 0, 2, 2), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 1, 0),
(1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 0), (1, 1, 2, 1), (1, 1, 2, 2),
(1, 2, 0, 0), (1, 2, 0, 1), (1, 2, 0, 2), (1, 2, 1, 0), (1, 2, 1, 1),
(1, 2, 1, 2), (1, 2, 2, 0), (1, 2, 2, 1), (1, 2, 2, 2), (2, 0, 0, 0),
(2, 0, 0, 1), (2, 0, 0, 2), (2, 0, 1, 0), (2, 0, 1, 1), (2, 0, 1, 2),
(2, 0, 2, 0), (2, 0, 2, 1), (2, 0, 2, 2), (2, 1, 0, 0), (2, 1, 0, 1),
(2, 1, 0, 2), (2, 1, 1, 0), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 2, 0),
(2, 1, 2, 1), (2, 1, 2, 2), (2, 2, 0, 0), (2, 2, 0, 1), (2, 2, 0, 2),
(2, 2, 1, 0), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 2, 0), (2, 2, 2, 1),
(2, 2, 2, 2)]
Run Code Online (Sandbox Code Playgroud)
在您的代码中,您可以:
for i,j,k,l in product(range(3),repeat=4):
#do stuff
Run Code Online (Sandbox Code Playgroud)
此函数等效于以下代码,但实际实现不会在内存中构建中间结果:
Run Code Online (Sandbox Code Playgroud)def product(*args, **kwds): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = map(tuple, args) * kwds.get('repeat', 1) result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod)
编辑:正如@ PeterE在评论中说的那样product()即使范围有不同的长度也可以使用:
product(range(3),range(4),['a','b','c'] ,some_other_iterable)
Run Code Online (Sandbox Code Playgroud)
FMc*_*FMc 15
使用的想法itertools.product很好.这是一种更通用的方法,可以支持不同大小的范围.
from itertools import product
def product_of_ranges(*ns):
for t in product(*map(range, ns)):
yield t
for i, j, k in product_of_ranges(4, 2, 3):
# do stuff
Run Code Online (Sandbox Code Playgroud)
Ser*_*sta 13
它不会更简洁,因为它会花费你一个发电机功能,但至少你不会被PEP8打扰:
def tup4(n):
for i in range(n):
for j in range(n):
for k in range(n):
for l in range(n):
yield (i, j, k, l)
for (i, j, k, l) in tup4(3):
# do your stuff
Run Code Online (Sandbox Code Playgroud)
(在python 2.x中你应该使用xrange而不是range在生成器函数中)
编辑:
当已知金字塔的深度时,上述方法应该是正确的.但您也可以在没有任何外部模块的情况下制作通用生成器:
def tup(n, m):
""" Generate all different tuples of size n consisting of integers < m """
l = [ 0 for i in range(n)]
def step(i):
if i == n : raise StopIteration()
l[i] += 1
if l[i] == m:
l[i] = 0
step(i+ 1)
while True:
yield tuple(l)
step(0)
for (l, k, j, i) in tup(4, 3):
# do your stuff
Run Code Online (Sandbox Code Playgroud)
(我用过,(l, k, j, i)因为在上面的发电机中,第一个指数先变化)
这相当于:
for c in range(3**4):
i = c // 3**3 % 3
j = c // 3**2 % 3
k = c // 3**1 % 3
l = c // 3**0 % 3
print(i,j,k,l)
Run Code Online (Sandbox Code Playgroud)
如果您一直这样做,请考虑使用通用生成器:
def nestedLoop(n, l):
return ((tuple((c//l**x%l for x in range(n-1,-1,-1)))) for c in range(l**n))
for (a,b,c,d) in nestedLoop(4,3):
print(a,b,c,d)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3758 次 |
| 最近记录: |