仅将列表推导用于副作用是否符合 Pythonic?

2024-11-20 08:44:00
admin
原创
8
摘要:问题描述:考虑一下我调用的函数的副作用,而不是返回值(例如打印到屏幕、更新 GUI、打印到文件等)。def fun_with_side_effects(x): ...side effects... return y 现在,使用列表推导来调用这个函数是否符合 Pythonic风格:[fun_wi...

问题描述:

考虑一下我调用的函数的副作用,而不是返回值(例如打印到屏幕、更新 GUI、打印到文件等)。

def fun_with_side_effects(x):
    ...side effects...
    return y

现在,使用列表推导来调用这个函数是否符合 Pythonic风格:

[fun_with_side_effects(x) for x in y if (...conditions...)]

请注意,我没有保存该列表

或者我应该像这样调用这个函数:

for x in y:
    if (...conditions...):
        fun_with_side_effects(x)

哪一个更好?为什么?


解决方案 1:

这样做非常违反 Python 规范,任何经验丰富的 Pythonista 都会因此而责怪你。中间列表在创建后会被丢弃,而且它可能非常非常大,因此创建起来非常昂贵。

解决方案 2:

您不应该使用列表推导,因为正如人们所说,这将构建一个您不需要的大型临时列表。以下两种方法是等效的:

consume(side_effects(x) for x in xs)

for x in xs:
    side_effects(x)

consume使用手册页中的定义itertools

def consume(iterator, n=None):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

当然,后者更加清楚,也更容易理解。

解决方案 3:

列表推导用于创建列表。除非您确实要创建列表,否则不应使用列表推导。

因此我会选择第二种选择,只需遍历列表,然后在条件适用时调用该函数。

解决方案 4:

第二个更好。

想想那些需要理解你的代码的人。对于第一个人来说,你很容易得到坏的报应 :)

你可以使用 filter() 在两者之间找到折中方案。请考虑以下示例:

y=[1,2,3,4,5,6]
def func(x):
    print "call with %r"%x

for x in filter(lambda x: x>3, y):
    func(x)

解决方案 5:

取决于你的目标。

如果您尝试对列表中的每个对象执行某些操作,则应采用第二种方法。

如果您尝试从另一个列表生成一个列表,则可以使用列表推导。

明确优于隐含。简单优于复杂。(Python Zen)

解决方案 6:

你可以做

for z in (fun_with_side_effects(x) for x in y if (...conditions...)): pass

但不太漂亮。

解决方案 7:

使用列表推导式来实现它的副作用是丑陋的、非 Python 的、低效的,我不会这么做。我会使用循环for,因为for循环表明了一种程序风格,其中副作用很重要。

但是,如果你坚持使用列表推导式来消除其副作用,那么你应该改用生成器表达式来避免效率低下的问题。如果你坚持使用这种风格,请执行以下两项操作之一:

any(fun_with_side_effects(x) and False for x in y if (...conditions...))

或者:

all(fun_with_side_effects(x) or True for x in y if (...conditions...))

这些是生成器表达式,它们不会生成随机列表并被丢弃。我认为这种all形式可能更清晰一些,尽管我认为它们都令人困惑,不应该使用。

我认为这很丑陋,我不会在代码中真正做到这一点。但如果你坚持以这种方式实现循环,我就会这样做。

我倾向于认为列表推导及其同类应该表明尝试使用至少与函数式风格略微相似的东西。将具有副作用的东西放入其中会破坏这一假设,这将导致人们不得不更仔细地阅读你的代码,我认为这是一件坏事。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用