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

时间:2017-05-01 20:24:38

标签: python python-3.x list-comprehension dictionary-comprehension

假设我的列表理解看起来像这样:

i = range(5)
a = [f(i) for i in i]

表示某个函数f。使用与迭代器相同的虚拟名称会产生意想不到的结果吗?有时我的变量名是单个字母,对我来说,坚持使用相同的字母而不是指定一个新字母更可读,比如[f(x) for x in x]而不是[f(i) for i in x](例如,如果这封信迭代器x有意义,我会想知道i到底是什么。

2 个答案:

答案 0 :(得分:9)

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

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

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

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

[f(x) for x in xs]

答案 1 :(得分:7)

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

然而,这导致了更为重要的一点。为什么要使用ijx之类的名称?使用单字母变量名称会引起混淆并且不明确。相反,使用一个明确传达你意图的变量名称。

或者,如果您对迭代中的值没有任何需求(例如,您只需要重复一段代码一段时间),请使用&#34 ;舍弃式"变量_,向读者传达您的代码值,这些值并不重要,应该被忽略。

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

因为最后,你宁愿维护像这样的代码

[str(x) for x in x]

还是这个?

[str(user_id) for user_id in user_ids]