不直观的UnboundLocalError行为的原因

bal*_*pha 5 python

注意:有一个非常类似的问题在这里.但是,请耐心等待; 我的问题不是"为什么会发生错误",而是"为什么Python实现为在这种情况下抛出错误."

我只是偶然发现了这个:

a = 5
def x()
    print a
    a = 6
x()
Run Code Online (Sandbox Code Playgroud)

抛出一个UnboundLocalException.现在,我确实知道为什么会发生这种情况(后来在这个范围内,a受到限制,因此a在整个范围内都被认为是本地的).

在这种情况下:

a = 5
def x()
    print b
    b = 6
x()
Run Code Online (Sandbox Code Playgroud)

这非常有意义.但第一种情况有一个直观的逻辑,这意味着:

a = 5
def x()
    print globals()["a"]
    a = 6 # local assignment
x()
Run Code Online (Sandbox Code Playgroud)

我想有一个原因是为什么不允许"直觉"版本,但它是什么?虽然这可能是"明确比隐含更好"的情况,但摆弄着globals()总觉得我有点不洁净.

从这个角度来看,发生在我身上的实际情况是别人的剧本,我不得不改变一下.在我的(短暂的)更改中,我在脚本运行时进行了一些文件重命名,所以我插入了

import os
os.rename("foo", "bar")
Run Code Online (Sandbox Code Playgroud)

进入脚本.这个插入发生在一个函数内部.模块已经os在顶级导入(我没有检查过),有些os.somefunction调用在函数内部进行,但在插入之前.这些电话显然触发了一个UnboundLocalException.

那么,有人可以向我解释这个实现背后的原因吗?是为了防止用户犯错误?"直观"的方式会让字节码编译器的内容变得更复杂吗?或者是否有一种我没有想到的歧义?

Ale*_*lli 6

具有相同的,相同的名称指的是在相同的线性代码流中完全不同的变量是如此令人难以置信的复杂性,它使思想错开.考虑:

def aaaargh(alist):
  for x in alist:
    print a
    a = 23
Run Code Online (Sandbox Code Playgroud)

这个代码应该在你想要的Python变体中做什么?有a在非常相同的print语句是指在环路的第一站完全不同的和无关变量VS第二个(假设有第二个)?对于一个项目的alist而言,它的工作方式是否与非循环代码不同?说真的,疯狂就是这样 - 甚至不考虑可怕的实现问题,只是试图记录和教导这可能会让我转换语言.

对于语言,其实施者,教师,学习者,实践者,承担所有这些概念负担,支持和鼓励全球变量的半隐藏,非显性使用,将会有什么基础?这似乎不值得一个目标,现在呢?!

  • ire_and_curses:在本地作用域中未声明的名称的外部作用域中查找有用的是允许您引用在全局作用域中定义/导入的函数,类和模块的内容.共享的全球状态并不坏; 共享*可变*全局状态是有风险的. (5认同)
  • +1,好吧,"这种疯狂的态度".编写语言似乎比使用它们复杂得多. (3认同)