Python列表理解与虚拟名称与迭代器名称相同:不明智?

Luk*_*vis 8 python list-comprehension python-3.x dictionary-comprehension

假设我做了一个类似于下面的列表理解:

i = range(5)
a = [f(i) for i in i]
Run Code Online (Sandbox Code Playgroud)

一些功能f.使用与迭代器相同的虚拟名称会产生意想不到的结果吗?有时候,我有变量名是单个字母,并且对我来说是更具可读性坚持使用相同的字母,而不是分配一个新的,像[f(x) for x in x]代替的[f(i) for i in x](例如,如果迭代的信x有意义的,我会想什么哎呀i).

wim*_*wim 9

TL; DR: 从技术上讲它是安全的,但在风格上它是一个糟糕的选择.

在列表解析中,在将for循环的自由变量绑定到任何对象之前,Python将使用GET_ITERiterable上的操作码来获取迭代器.这只在循环开始时完成一次.

因此,在列表推导的"循环"(实际上在Python 3中创建一个范围)的主体中,您可以重新绑定最初指向迭代的名称而不会产生任何后果.迭代直接处理对迭代器的引用,并且它是否在范围内具有名称是无关紧要的.在Python 2中也应该如此,尽管范围实现细节是不同的:在理解之后集合的名称将丢失,因为循环变量名称将保持绑定到迭代的最终元素.

以这种方式编写代码没有任何好处,并且它的可读性低于避免名称冲突.因此,您应该更喜欢为集合命名,以便更明显它是一个集合:

[f(x) for x in xs]
Run Code Online (Sandbox Code Playgroud)

  • 在Python 2中,事物(通常)不会在理解本身中破坏,但是一旦在理解之后任何东西试图使用"i"就会中断,因为理解力踩在了"i"的原始值上. (6认同)

Chr*_*ean 7

虽然由于Python执行列表推导的方式(甚至是嵌套列表推导),你可以使用重复的变量名来逃避, 但不要这样做.在您看来,它可能看起来更具可读性,但对于大多数人来说,这将是非常令人困惑的.

然而,这导致了更重要的一点.为什么要使用一个名称,如i,jx在所有?使用单字母变量名称会引起混淆并且不明确.相反,使用一个清楚传达你意图的变量名称.

或者,如果您根本不需要迭代中的值(例如,您只需要重复一段代码一段次),请使用"丢弃"变量_,向读者传达你的代码,价值并不重要,应该被忽略.

但是,请勿使用非描述性,重复的单字母变量名称.这只会让您的代码混淆未来的读者,使您的意图不明确,并创建难以维护和调试的代码.

因为最后,您是否愿意维护这样的代码

[str(x) for x in x]
Run Code Online (Sandbox Code Playgroud)

或这个?

[str(user_id) for user_id in user_ids]
Run Code Online (Sandbox Code Playgroud)

  • 另外,如果你想使用**pdb.set_trace()**调试,一个字母变量会与pdb命令发生很多名称冲突. (3认同)