假设我的列表理解看起来像这样:
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
到底是什么。
答案 0 :(得分:9)
TL; DR:从技术上讲,它是安全的,但在风格上它是一个糟糕的选择。
在列表解析中,在将for循环的自由变量绑定到任何对象之前,Python将在iterable上使用GET_ITER
操作码来获取迭代器。这只是在循环开始时一次完成的。
因此,在列表推导的“循环”(实际上在Python 3中创建一个范围)的主体中,您可以重新绑定最初指向迭代的名称而不会产生任何后果。迭代直接处理对 iterator 的引用,并且它是否在范围内具有名称是无关紧要的。在Python 2中也应该如此,尽管范围实现细节是不同的:在理解之后集合的名称将丢失,因为循环变量名称将保持绑定到迭代的最终元素。
以这种方式编写代码没有任何好处,并且它的可读性低于避免名称冲突。因此,您应该更喜欢为集合命名,以便更明显它是一个集合:
[f(x) for x in xs]
答案 1 :(得分:7)
由于Python执行列表推导的方式 - 甚至是嵌套列表推导 - 你可以使用重复的变量名称 - 不要这样做。在您看来,它可能看起来更具可读性,但对于大多数人来说,这将非常令人困惑。
然而,这导致了更为重要的一点。为什么要使用i
,j
或x
之类的名称?使用单字母变量名称会引起混淆并且不明确。相反,使用一个明确传达你意图的变量名称。
或者,如果您对迭代中的值没有任何需求(例如,您只需要重复一段代码一段时间),请使用&#34 ;舍弃式"变量_
,向读者传达您的代码值,这些值并不重要,应该被忽略。
但请勿使用非描述性,重复的单字母变量名称。这只会让您的代码混淆未来的读者,使您的意图不明确,并创建难以维护和调试的代码。
因为最后,你宁愿维护像这样的代码
[str(x) for x in x]
还是这个?
[str(user_id) for user_id in user_ids]