当前位置: 首页 > 面试题库 >

Python-即使在理解范围之后,列表理解也会重新绑定名称。是这样吗?

公孙栋
2023-03-14
问题内容

理解与范围界定存在一些意外的相互作用。这是预期的行为吗?

我有一个方法:

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的创建者)解释了其背后的历史:

我们还对Python 3进行了另一处更改,以改善列表理解与生成器表达式之间的等效性。在Python 2中,列表理解将“循环”控制变量“泄漏”到周围的范围内:

x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'

这是列表理解的原始实现的产物。多年来,它一直是Python的“肮脏的小秘密”之一。它起初是一种有意的折衷,目的是使列表理解迅速变得盲目,虽然对于初学者来说这不是一个常见的陷阱,但它肯定偶尔会刺痛人们。对于生成器表达式,我们无法执行此操作。生成器表达式是使用生成器实现的,生成器的执行需要单独的执行框架。因此,生成器表达式(特别是如果它们在短序列上进行迭代)比列表理解效率低。

但是,在Python 3中,我们决定通过使用与生成器表达式相同的实现策略来修复列表理解的“肮脏的小秘密”。因此,在Python 3中,上述示例(在修改为使用print(x):-之后)将打印“ before”,证明列表理解中的“ x”会暂时遮盖阴影,但不会覆盖周围的“ x”范围。



 类似资料:
  • 问题内容: 解释我的问题的最好方法是举一个例子: example.py: 当我在python 2下运行它时,它工作正常,但是在python 3下,我得到了for类(但不是class ): 为什么只有class会引发a ,为什么只在Python 3下? 问题答案: 类作用域在Python 3中有点奇怪,但这是有充分理由的。 在Python 2中,迭代变量(以及您的示例中)从列表理解中泄漏出来,并将包

  • 我正在处理一个使用Spring批处理的项目。在本项目中,我使用Spring批处理后期绑定,其中我使用JobParameters注入了一个参数(将用作SQL读取器查询的条件的字符串)。目前,我正在使用进行后期绑定,所有操作都非常正常。 这里我要问的是何时使用以及何时使用。我已经阅读了Spring批处理参考文件,并在谷歌上搜索了StepScope和jobscope。我得到的只是: a.StepScop

  • 问题内容: 我有一个包含10个元素的div,这些元素将被逐个更新,延迟时间为2秒。下面是相同的代码 但是,当我运行它时,所有元素都会一起更新。该程序只是添加一个延迟添加一个开始,并且所有元素都一起更新(被标记)。如何制作代码来逐一标记元素? 问题答案: 您正在打破React的两个基本规则: 不要直接改变状态 如果根据现有状态更新状态,请使用回调形式,因为状态更新可能是异步的(无论如何,在您的示例中

  • 问题内容: 我有一个列表,我只想在满足特定条件的条目上使用特定功能-保留其他条目不变。 例如:假设我只想将偶数个元素乘以2。 想要的结果: 但是产量(它还充当过滤器)。 正确的解决方法是什么? 问题答案: 使用条件表达式: (数学怪人的注:您也可以使用 但无论如何我还是更喜欢第一种选择;)

  • 我们知道Spring框架提供了单例、原型、请求、会话、全局会话bean范围。 我们还知道Spring Web流提供了flow Scope、viewScope、Request estScope、flash Scope、versationScope。 因此,如果我在spring MVC项目中提到一个组件,比如说Student,作为@Component@Scope=singleton。对于每个请求,它会

  • 我使用一个简单的1D纹理将一组值动态传递给我的像素着色器。我希望能够随时更新这些数组值(以及数组的大小)。目前,我正在使用序列 为此。虽然这在初始化时工作正常,但在渲染期间(在键盘输入上)执行这些行会在之后产生。 那么,在更新纹理之前,我需要停用或解除绑定纹理吗?