繁体   English   中英

将 function 应用于列表的某些项目的最pythonic方法是什么?

[英]What is the most pythonic way to apply function to some items of a list?

让我们使用这段代码打印列表的所有正面 integer :

l = [1, -1, 1, 0, 2]
for i in l:
   if i > 0:
       print(i)

我可以通过列表理解来做到这一点,但我想这对创建一个新的无用列表有不利之处:

[print(i) for i in l if i > 0]

所以我的问题是:有没有更 Pythonic 的方式来写这个?

普通的 for 循环是完全 Pythonic 的。 您想遍历列表的元素 select 大于零的元素,然后打印它们,这正是它所做的 - 不多也不少。

列表理解不是 Pythonic ,主要是因为您给出的原因:它创建了一个新的无用列表。 即使您打算使用 list ,使用列表推导来处理副作用仍然是不好的做法。

将 function 应用于元素列表的某个子集的最 Pythonic 方法是使用for循环,就像您已经拥有的一样。

在那个for循环中,在将任何值分配给i之前,有一个参数用于过滤列表; 这是否构成改进通常是一个见仁见智的问题,将取决于具体情况。

for i in filter(lambda x: x > 0, l):
    print(i)

在这种情况下,我认为情况更糟。 但有时你手头有一个谓词,过滤在语法上可以更轻松。 相比

for i in some_list_of_strings:
    if i.isdigit():
        print(i)

for i in filter(str.isdigit, some_list_of_strings):
    print(i)

我想理论上你可以设法使用生成器理解以避免在 memory 中创建一个大列表:

for _ in (print(i) for i in l if i > 0): pass

(也许还使用一些 function 来消耗来自生成器的值,因此任何循环都隐藏在该函数内)。

但是,这不仅比显式for循环可读性差,而且纯for循环也更快。

import time

l = [1, -1, 1, 0, 2]

# we don't really want lots of output for this timing test
def dont_really_print(i):
    return i

t1 = time.time()

for x in range(1000000):
    for i in l:
        if i > 0:
            dont_really_print(i)

t2 = time.time()

for x in range(1000000):
    for _ in (dont_really_print(i) for i in l if i > 0):
        pass

t3 = time.time()

print(f"generator comprehension {t3 - t2:.3f} "
      f"explicit loop {t2 - t1:.3f}")

给出:

generator comprehension 0.629 explicit loop 0.423

通常,无论是 Python 还是其他任何语言,您要做的事情都称为“地图”。

打印是一个奇怪的 function 到 map,所以这里是另一个 function 用于更好的演示目的。

def add_one(num):
    return num + 1

foo = [1, 2, 3, 4]
new_list = map(add_one, foo)
print(list(new_list))

您通常可以并行使用 map,有时是异步的,并且大量并行处理范例(包括 Python 的多处理)使用 map 作为使用多核实现 ZC1C425268E68385D1AB5074C14 的基本操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM