【问题标题】:What is a cell in the context of an interpreter or compiler?解释器或编译器上下文中的单元格是什么?
【发布时间】:2014-05-20 10:22:38
【问题描述】:

Python 代码对象有一个属性co_cellvarsPyPy's bytecode interpreter 的文档经常使用术语Cell

在其他语言中,Rust provides a Cell datatype。谷歌搜索表明它们以某种方式与闭包有关。

在编程语言实现的上下文中,cell 是什么?细胞解决了什么问题?

【问题讨论】:

  • 在 Rust 中,Cell 只是一种绕过继承不变性的方法,以便您可以修改数据,尽管对它有不可变的引用。这与 Python 的含义完全不同。你知道,“细胞”是一个非常通用的术语。
  • @ChrisMorgan 听起来您在我提到的两种情况下都熟悉 Cell。您愿意提交答案吗?
  • 我不太熟悉 Python 代码对象表示的内部结构,但我可以猜到“单元格”的含义。

标签: python compiler-construction closures interpreter rust


【解决方案1】:

在 Python 中,cell 对象用于存储closurefree variables

假设您想要一个始终返回其参数的特定部分的函数。您可以使用闭包来实现:

def multiplier(n, d):
    """Return a function that multiplies its argument by n/d."""
    def multiply(x):
        """Multiply x by n/d."""
        return x * n / d
    return multiply

你可以这样使用它:

>>> two_thirds = multiplier(2, 3)
>>> two_thirds(7)
4.666666666666667

two_thirds 如何记住nd 的值?它们不是multiplier 定义的multiply 函数的参数,它们不是在multiply 中定义的局部变量,它们不是全局变量,并且由于multiplier 已经终止,它的局部变量不再存在对吧?

multiplier 被编译时,解释器注意到multiply 稍后将要使用它的局部变量,所以它会记录它们:

>>> multiplier.__code__.co_cellvars
('d', 'n')

然后当multiplier被调用时,那些外部局部变量的值被存储在返回函数的__closure__属性中,作为cell对象的元组:

>>> two_thirds.__closure__
(<cell at 0x7f7a81282678: int object at 0x88ef60>,
 <cell at 0x7f7a81282738: int object at 0x88ef40>)

...在__code__ 对象中的名称为co_freevars

>>> two_thirds.__code__.co_freevars
('d', 'n')

您可以使用它们的cell_contents 属性获取单元格的内容:

>>> {v: c.cell_contents for v, c in zip(
        two_thirds.__code__.co_freevars,
        two_thirds.__closure__
)}
{'d': 3, 'n': 2}

您可以在介绍闭包的 Python 增强提案中了解更多关于闭包及其实现的信息:PEP 227 — Statically Nested Scopes

【讨论】:

  • 是否可以修改这些存储变量之一以在创建后更改函数? (例如 d = 5)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 2020-10-27
  • 2012-08-28
  • 2010-10-03
  • 1970-01-01
相关资源
最近更新 更多