我有一个基本的“餐巾算法”,它采用元组列表(包含2个项目)并更改它们。这是英文版:
这是我放在一起的快速功能:
def f(objects):
list_type = "string_x"
other = "string_y"
hold = []
for x in objects:
if isinstance(x[1],list):
hold.append((list_type,x[1]))
else:
hold.append((other,x[1]))
return hold
我不相信这是最有效的方式。该算法非常简单,只是一个基本的陈述。 这样做的效率更高?
答案 0 :(得分:2)
您可以使用if
表达式将其缩短一点:
def f(objects):
list_type = "string_x"
other = "string_y"
hold = []
for x in objects:
hold.append((list_type if isinstance(x[1], list) else other, x[1]))
return hold
然后很容易变成一种理解,这种理解甚至更短,可能更具可读性,更快一点:*
def f(objects):
list_type = "string_x"
other = "string_y"
return [(list_type if isinstance(x[1], list) else other, x[1])
for x in objects]
实际上,我不确定那些局部变量是否使事情变得更清楚:**
def f(objects):
return [("string_x" if isinstance(x[1], list) else "string_y", x[1])
for x in objects]
同时,如果你要对返回的列表做的唯一事情就是迭代它(例如,因为这只是一个转换链中的一个),你根本不应该返回一个列表。每个值yield
,返回genexpr而不是listcomp,或者(如果你有Python 3.3+)获得两全其美:
def f(objects):
yield from (("string_x" if isinstance(x[1], list) else "string_y", x[1])
for x in objects)
*您仍在执行完全相同的循环,因此您具有完全相同的算法复杂度。但是,循环和列表追加都发生在自定义字节码中,这些字节码采用了一些快捷方式,使每次迭代更有效。 (“自定义字节码”详细信息当然特定于CPython和其他字节码兼容的实现,如PyPy,但一般来说,任何实现至少都可以采用列表推导的快捷方式。)
**最后这个可能会稍快一些,因为它将一个常量加载到堆栈而不是局部变量。然后,它可能也有稍微更糟糕的缓存局部性。如果真的很重要,请测试并查看。
答案 1 :(得分:0)
使用列表理解会更有效率和 pythonic (如果我没错):
[("string_x" if isinstance(x[1], list) else "string_y", x[1]) for x in objects]
答案 2 :(得分:0)
如果您需要检查并更改列表中的所有项目,则需要循环,否则您无法执行此操作。
你可以使用列表理解使其快一点,这减少了每个列表项的追加功能。
def f(objects):
return [('string_x',x[1]) if isinstance(x[1],list) else ('string_y',x[1]) for x in objects]
但只有在使用大型列表
时才会看到性能差异答案 3 :(得分:0)
我有点像这样做,但我可能是一个愚蠢的人:
strings = 'string_x', 'string_y'
[(strings[isinstance(x[1],list)], x[1]) for x in objects]