如果函数需要修改在全局范围内声明的变量,则需要使用全局声明.但是,如果函数只需要读取全局变量,它可以在不使用全局声明的情况下执行此操作:
X = 10
def foo():
global X
X = 20 # Needs global declaration
def bar():
print( X ) # Does not need global
Run Code Online (Sandbox Code Playgroud)
我的问题是关于Python的设计:为什么Python设计为允许读取全局变量而不使用全局声明?也就是说,为什么只有强制赋值具有全局性,为什么不强制全局读取呢?(这会使它变得均匀而优雅.)
注意:我可以看到在阅读时没有歧义,但是在分配时不清楚是否打算创建新的局部变量或分配给全局变量.但是,我希望BDFL对这种不均衡的设计选择有更好的理由或意图.
Ray*_*ger 27
使用嵌套作用域,变量查找很容易.它们出现在从本地开始的链中,通过封闭defs,到模块全局变量,然后是内置变量.规则是找到胜利的第一场比赛.因此,您不需要查找"全局"声明.
相反,对于写入,您需要指定要写入的范围.否则无法确定函数中的"x = 10"是否意味着"写入本地命名空间"或"写入全局命名空间".
执行摘要,写入您可以选择命名空间,但查找第一个找到的规则就足够了.希望这可以帮助 :-)
编辑:是的,就是这种方式"因为BDFL这么说",但是在没有类型声明的其他语言中,有一个首先找到的查找规则并且只需要一个非本地写入的修饰符.当你考虑它时,这两个规则导致非常干净的代码,因为范围修饰符只在最不常见的情况下需要(非本地写入).
Ned*_*der 17
看看这段代码:
from module import function
def foo(x):
return function(x)
Run Code Online (Sandbox Code Playgroud)
function这里的名字是全球性的.如果我不得不说global function让这段代码工作,那将会非常繁琐.
在你说你X和我function的不同之前(因为一个是变量而另一个是导入的函数),请记住Python中的所有名称都被视为相同:使用时,它们的值在范围层次结构中被查找.如果你需要global X那么你需要global function.伊克.
Ped*_*eck 16
因为显性优于隐式.
读取变量时没有歧义.在从本地搜索范围到全局范围时,总是会找到第一个找到的.
分配时,解释器可能只明确假设您分配的两个范围:本地和全局.由于分配到本地是最常见的情况,实际上不鼓励分配给全局,这是默认情况.要分配给全局,您必须明确地执行此操作,告诉解释器无论您在此范围内使用该变量,它都应直接进入全局范围,并且您知道自己在做什么.在Python 3上,您还可以使用"nonlocal"分配到最近的封闭范围.
请记住,当您在Python中分配名称时,此新分配与先前分配给其他名称的名称无关.想象一下,如果没有默认的本地,Python搜索了所有范围,试图找到一个具有该名称的变量,并像读取时一样分配给它.您的函数的行为可能不仅基于您的参数而且基于封闭范围而更改.生活会很悲惨.
你自己说,读取没有歧义,而且有写作.因此,您需要一些机制来解决写入的歧义.
一个选项(可能实际上被许多旧版本的Python使用,IIRC)只是说写入总是转到本地范围.然后就不需要global关键字,也没有歧义.但是你根本不能写入全局变量(不使用像globals()往返一样的东西),所以这不会很好.
静态声明变量的语言使用的另一个选项是预先与语言实现进行通信,以查找名称为本地的每个范围(您在该范围内声明的范围)以及哪些名称是全局的(在模块范围内声明的名称) .但Python没有声明变量,所以这个解决方案不起作用.
另一种选择是x = 3仅在某个具有名称的外部作用域中没有名称时才分配给局部变量x.似乎它会直观地做正确的事情?这会导致一些严重恶劣的角落案件.目前,x = 3写入的位置由解析器静态确定; 要么global x在相同的范围内没有,这是一个本地写,或者有一个global x,它是一个全局写.但是如果它将做什么取决于全局模块范围,则必须等到运行时才能确定写入的位置,这意味着它可以在函数的调用之间进行更改.考虑一下.每次在模块中创建全局时,都会改变模块中所有函数的行为,这些函数恰好使用该名称作为局部变量名.做一些tmp用作临时变量的模块范围计算,并告别在模块tmp中的所有函数中使用.我不禁想到隐藏的错误,包括在您导入的模块上分配属性,然后从该模块调用函数.哎呀.
另一个选择是与每个分配的语言实现进行通信,无论它是本地的还是全局的.这就是Python的用武之地.鉴于有一个合理的默认值几乎涵盖了所有情况(写入局部变量),我们将局部赋值作为默认值并明确标出全局赋值global.
分配存在歧义,需要一些机制来解决它.global就是这样一种机制.它不是唯一可能的,但在Python的背景下,似乎所有替代机制都是可怕的.我不知道你正在寻找什么样的"更好的理由".
| 归档时间: |
|
| 查看次数: |
5945 次 |
| 最近记录: |