gpt4 book ai didi

python - 为什么 Python 的列表推导式不复制参数以便实际对象不能被改变?

转载 作者:太空宇宙 更新时间:2023-11-04 06:44:34 25 4
gpt4 key购买 nike

也许我喝了太多函数式编程 Kool Aid,但这种列表理解的行为似乎是一个糟糕的设计选择:

>>> d = [1, 2, 3, 4, 5]
>>> [d.pop() for _ in range(len(d))]
[5, 4, 3, 2, 1]
>>> d
[]

为什么 d 没有被复制,然后复制的词法范围版本没有发生变异(然后丢失)?列表理解的要点似乎应该是返回所需的列表,而不是返回列表并在幕后默默地改变其他一些对象。 d 的破坏有点隐含,这似乎是非 Pythonic 的。这有一个很好的用例吗?

为什么让 list comps 的行为完全像 for 循环而不是更像函数(来自函数式语言,具有局部作用域)是有利的?

最佳答案

除非您明确要求 Python 进行复制,否则 Python 从不进行复制。这是一个非常简单、清晰且完全可以理解的规则。将异常(exception)和区别放在上面,例如“除了在列表理解中的以下情况下......”,将是完全愚蠢的:如果 Python 的设计曾经处于具有如此疯狂想法的人的管理之下,Python 将是一个病态,扭曲的,半 splinter 的语言不值得学习。感谢你让我再次开心,因为我意识到这绝对是不是的!

你想要一份吗? 制作一份副本!当您更喜欢副本的开销时,这就是 Python 中的始终解决方案,因为您需要执行一些不能反射(reflect)在原始文件中的更改。也就是说,在 clean 方法中,您会这样做

dcopy = list(d)
[dcopy.pop() for _ in range(len(d))]

如果您 super 热衷于将所有内容都包含在一个表达式中,您可以,尽管它可能不是人们会称之为“干净”的代码:

[dcopy.pop() for dcopy in [list(d)] for _ in range(len(d))]

即,当人们真的想将赋值折叠到列表推导中时使用的常用技巧(添加一个 for 子句,“控制变量”是您要分配给的名称,并且“循环”在您要分配的值的单项序列上)。

函数式语言从不改变数据,因此它们也不会制作副本(也不需要)。 Python 不是一种函数式语言,但当然您可以在 Python 中以“函数式方式”做很多事情,而且通常它是一种更好的方式。例如,一个好得多的列表理解替代品(保证有相同的结果并且不影响d,并且大大更快,更简洁,和清洁工):

d[::-1]

(又名“火星笑脸”,据我妻子安娜说;-)。切片(不是切片 assignment,这是不同的操作)总是在核心 Python(语言和标准库)中执行复制,当然不一定像流行的 这样独立开发的第三方模块numpy(它更喜欢将切片视为原始 numpy.array 上的“ View ”)。

关于python - 为什么 Python 的列表推导式不复制参数以便实际对象不能被改变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3538826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com