Python列表解析重新绑定名称,即使在理解范围之后。这是正确的吗?

列表推导与范围界定有一些意想不到的交互。这是预期的行为吗?

我有一个方法:

def leave_room(self, uid):
  u = self.user_by_id(uid)
  r = self.rooms[u.rid]

  other_uids = [ouid for ouid in r.users_by_id.keys() if ouid != u.uid]
  other_us = [self.user_by_id(uid) for uid in other_uids]

  r.remove_user(uid) # OOPS! uid has been re-bound by the list comprehension above

  # Interestingly, it's rebound to the last uid in the list, so the error only shows
  # up when len > 1

有鞭打的危险,这是一个残酷的错误来源。当我写新的代码,我只是偶尔发现非常奇怪的错误,由于重新绑定 – 即使现在,我知道这是一个问题。我需要一个规则像“总是前面temp vars在列表推导下划线”,但即使这不是傻瓜。

事实上,有这种随机的时间炸弹等待类型否定了所有好的“易用性”的列表推导。

列表推导漏洞在Python 2中循环控制变量,但不是在Python 3中。这里是Guido van Rossum(Python的创造者)explaining的历史背后:

We also made another change in Python
3, to improve equivalence between list
comprehensions and generator
expressions. In Python 2, the list
comprehension “leaks” the loop control
variable into the surrounding scope:

06000

This was an artifact of the original
implementation of list comprehensions;
it was one of Python’s “dirty little
secrets” for years. It started out as
an intentional compromise to make list
comprehensions blindingly fast, and
while it was not a common pitfall for
beginners, it definitely stung people
occasionally. For generator
expressions we could not do this.
Generator expressions are implemented
using generators, whose execution
requires a separate execution frame.
Thus, generator expressions
(especially if they iterate over a
short sequence) were less efficient
than list comprehensions.

However, in Python 3, we decided to
fix the “dirty little secret” of list
comprehensions by using the same
implementation strategy as for
generator expressions. Thus, in Python
3, the above example (after
modification to use print(x) 🙂 will
print ‘before’, proving that the ‘x’
in the list comprehension temporarily
shadows but does not override the ‘x’
in the surrounding scope.

http://stackoverflow.com/questions/4198906/python-list-comprehension-rebind-names-even-after-scope-of-comprehension-is-thi

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:Python列表解析重新绑定名称,即使在理解范围之后。这是正确的吗?