为什么“ ord”在这里被视为未分配变量?

为什么“ ord”在这里被视为未分配变量?,第1张

为什么“ ord”在这里被视为未分配变量

这与编译器在编译为字节码时基于不相关分支进行静态分析无关;这要简单得多。

Python有一个区分全局变量,闭包变量和局部变量的规则。在函数中分配的所有变量(包括隐式分配给参数的参数)都是局部变量(除非它们具有

global
or
nonlocal
语句)。参考文档的“绑定和命名”及后续章节对此进行了说明。

这并不是要使解释器简单,而是要使规则足够简单以使人类读者通常可以直观地理解,并且在不直观时可以很容易地被人解决。(这对于此类情况尤其重要-
行为并非到处都是直观的,因此Python将规则保持足够简单,以使一旦学习,该情况仍然很明显。但是您肯定必须在此之前学习该规则是的,当然,大多数人是第一次对规则感到惊讶来学习该规则的…)

即使优化器足够聪明,可以完全删除与之相关的任何字节码

if False: ord=None
ord
但根据语言语义规则,仍必须是局部变量。

因此:

ord=
函数中有一个,因此对的所有引用
ord
都是对局部变量的引用,而不是碰巧具有相同名称的任何全局或非局部变量,因此您的代码是
UnboundLocalError


许多人在不了解实际规则的情况下走了过来,而是使用了更简单的规则:变量是

  • 如果可能,则为本地,否则为
  • 如果可能,将其封闭,否则
  • 如果是全局变量,则为全局变量,否则
  • 内置(如果内置),否则
  • 一个错误

尽管这种方法在大多数情况下都有效,但在某些情况下(例如这种情况)可能会产生误导。具有以Lisp样式完成LEGB范围界定的语言会看到它

ord
不在本地名称空间中,因此会返回全局名称,但Python不会这样做。您可以说这
ord


在本地名称空间中,但是绑定到一个特殊的“未定义”值,它实际上接近幕后发生的事情,但这不是Python规则所说的,尽管这样做可能更直观简单的情况下,很难进行推理。


如果您好奇这是如何工作的,请执行以下 *** 作:

在CPython中,编译器将扫描您的函数以查找所有以标识符为目标的赋值,并将其存储在数组中。它删除全局变量和非局部变量。该数组最终将作为您的代码对象的数组

co_varnames
,因此,假设您
ord
co_varnames[1]
。然后,对该变量的每次使用都会编译为
LOAD_FAST1
STORE_FAST 1
,而不是编译为
LOAD_NAME
STORE_GLOBAL
或其他 *** 作。解释时,这
LOAD_FAST1
只是将框架的内容加载
f_locals[1]
到堆栈中。它
f_locals
以NULL指针数组而不是指向Python对象的指针开始,如果
LOAD_FAST
加载了NULL指针,它将引发
UnboundLocalError



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5645710.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存