使用一个行循环,甚至嵌套循环总是Python中的一个好习惯吗?我看到很多人只是喜欢和#34; one-liners",但对我来说,他们有时难以阅读,特别是如果我们谈论嵌套循环。
此外,我到目前为止看到的大多数嵌套循环都超过了每行推荐的79个字符。
所以我想知道" one-liners"提供紧凑的任何额外的东西?他们可能会使用更少的内存吗?
答案 0 :(得分:5)
是的,它们可能更容易更快,因为可以在C中运行更多代码(在显式循环中,所有直接步骤必须可用于解释器,在一线列表理解中它不必)。还有.append
方法调用,方法查找等的开销。在列表理解中,所有这些都被避免了:
import timeit
def f1():
result = []
for x in range(100):
for y in range(100):
result.append(x * y)
return result
def f2():
return [x * y for y in range(100) for x in range(100)]
print('loop: ', timeit.timeit(f1, number=1000))
print('oneliner:', timeit.timeit(f2, number=1000))
结果(Python 3):
loop: 1.2545137699926272
oneliner: 0.6745600730064325
答案 1 :(得分:1)
取决于单行,有些可以更高效,更易读。
以列表理解为例。假设您想要从1到10中取所有数字并输出其产品列表乘以2.
输入:[1,2,3,...,9,10]
输出:[2,4,6,...,18,20]
您可以在for循环中执行此操作:
output = []
for i in range(1, 11):
output.append(i*2)
或者你可以使用列表理解:
[i*2 for i in range(1,11)]
您会看到列表理解速度更快,而且非常易读。
对于词典理解,集合理解和生成器表达式也可以这样说。此外,只要可以理解,map()
和filter()
的使用就会受到高度鼓励。
答案 2 :(得分:0)
For discussion... they all do the same.
'a' a list comprehension... the smoking one-liner... 'b' same thing, but you can provide annotation within a list comprehension... it is still technically a one-liner 'c' the conventional approach. If speed is a concern, I am less worried about the speed unless, I perform the same task day in day out and it takes a really long time to perform. Comparing speed when you are talking micro or nanoseconds may be of academic interest, but it will not impact the vast majority of users. I always vote for clarity of expression over compactness of code.
a = [i**2 for i in range(20) if i > 5 and i < 10]
b = [i**2 # do this
for i in range(20) # using these
if (i > 5) and # where this and
(i < 10) # this is good
]
c = []
for i in range(20):
if (i > 5) and (i < 10):
c.append(i**2)
EDIT The example given of producing the product of a range of numbers, is a good indicator, that the oneliner need not be the issue, but the method used to obtain the result. I will illustrate with determining the product using only 10 values... try it with 100 if you like. I will do it in full format, but could reduce everything to a oneliner if need (import excluded).
>>> import numpy as np
>>> a = np.arange(10)
>>> b = np.arange(10).reshape(10,1)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
>>> a*b
array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
[ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27],
[ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36],
[ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45],
[ 0, 6, 12, 18, 24, 30, 36, 42, 48, 54],
[ 0, 7, 14, 21, 28, 35, 42, 49, 56, 63],
[ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72],
[ 0, 9, 18, 27, 36, 45, 54, 63, 72, 81]])
or as a one-liner
>>> out = np.arange(10) * np.arange(10).reshape(10,1)
and of course there are built-in functions to do this without the full expression I have shown.
The point being made, speed isn't everything. Clarity of code AND choosing the right tools to do the job should be considered first.
答案 3 :(得分:-1)
是。这是一种很好的做法。
通常有经验的程序员在单行循环中使用匿名函数(参见lambda:http://www.secnetix.de/olli/Python/lambda_functions.hawk),它会提供更好的性能。