Python: Why is global needed only on assignment and not on reads?
如果函数需要修改在全局范围中声明的变量,则需要使用全局声明。但是,如果函数只需要读取一个全局变量,那么它可以在不使用全局声明的情况下这样做:
1 2 3 4 5 6 | X = 10 def foo(): global X X = 20 # Needs global declaration def bar(): print( X ) # Does not need global |
我的问题是关于python的设计:为什么python设计为允许在不使用全局声明的情况下读取全局变量?也就是说,为什么只有强制分配具有全局性,为什么不强制全局读取呢?(这会使它变得均匀和优雅。)
注意:我可以看到,在读取时没有歧义,但是在分配时,不清楚是要创建一个新的局部变量还是要分配给全局变量。但是,我希望有一个更好的理由或意图,这种不平衡的设计选择,由BDFL。
使用嵌套范围,变量查找很容易。它们发生在一个链中,从局部变量开始,通过封闭def,到模块全局变量,然后是内置的。规则是第一场比赛获胜。因此,查找不需要"全局"声明。
相反,对于写操作,您需要指定要写入的范围。否则,无法确定函数中的"x=10"是指"写入本地命名空间"还是"写入全局命名空间"。
执行摘要,使用write,您可以选择名称空间,但是使用查找,第一个找到的规则就足够了。希望这有帮助:—)
编辑:是的,是这样的,"因为bdfl是这么说的",但在没有类型声明的其他语言中,查找的第一个找到的规则和非本地写入只需要一个修饰符并不罕见。当您考虑它时,这两个规则会导致非常干净的代码,因为范围修饰符只在最不常见的情况下需要(非本地写入)。
查看此代码:
1 2 3 4 | from module import function def foo(x): return function(x) |
这里的名字是一个全球性的。如果我不得不说
在你说你的
因为显式比隐式好。
当你读一个变量的时候没有歧义。从本地搜索范围到全局搜索范围时,始终会找到第一个。
当您分配时,解释器可能明确地假设您分配给两个作用域:本地和全局。因为分配给本地是最常见的情况,而分配给全局实际上是不鼓励的,所以它是默认的。要分配给global,您必须显式地进行分配,告诉解释器在这个范围内的任何地方使用这个变量,它都应该直接转到global范围,并且您知道自己在做什么。在python 3上,您还可以使用"nonlocal"分配到最近的封闭范围。
记住,当您在python中分配一个名称时,这个新的分配与以前分配给其他对象的名称没有任何关系。想象一下,如果没有默认的local和python搜索所有范围,试图找到一个具有该名称的变量,并像读取时那样分配给它。函数的行为不仅可以根据参数,还可以根据封闭范围进行更改。生活将是悲惨的。
你自己说,读没有歧义,写有歧义。因此,您需要一些机制来解决写操作中的歧义。
一个选项(可能实际上被很多旧版本的python,iirc使用)就是说写操作总是转到本地范围。那么就不需要使用
静态声明变量的语言使用的另一个选项是,为每个名称是本地(在该范围中声明的名称)和全局(在模块范围中声明的名称)的范围预先与语言实现通信。但是python没有声明变量,所以这个解决方案不起作用。
另一种选择是,只有在某些外部作用域中没有名为
另一种选择是在每个任务上与语言实现通信,无论它应该是本地的还是全局的。这就是Python的风格。考虑到存在几乎涵盖所有情况(写入局部变量)的合理默认,我们将局部赋值作为默认值,并使用
分配中存在歧义,需要某种机制来解决它。