好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

为什么Python不是lexicalscoping?

这似乎背离了现代程序设计语言的一般设计思路。

比如

 def   foo  (): 
     x   =   1 
     def   inner  (): 
         return   x   +   1 
     x   =   3 
     print   inner  () 
 

回复内容: 这段代码是lexical scoping,静态作用域是指我们可以根据代码文本的位置,确定变量的存在区域。

按照python的LEGB(Local,Enclosing,Global,Built-in)规则,当调用inner()时,x实际上是在foo的scope中找到的。inner之所能够访问foo中的x,是因为inner is inside the text of foo,这正是lexical的含义 。

Bash是Dynamic Scoping的

  x  =  1                                                                                                  
 function  g  ()   {   echo   $x   ;   x  =  2   ;   }  
 function  f  ()   {   local   x  =  3   ;  g  ;   }  
f   #f中的g执行时打印出的x是3而不是1 
 echo   $x    #这时打印出的x是1 
  
你以为Python是

  let   foo   ()   = 
   let   x   =   1   in 
     let   inner   ()   =   x   +   1   in 
       let   x   =   3   in 
         print   (  inner   ()  ) 
  
python的闭包里的自由变量是按引用传递的,而不是按值传递,所以会有这个结果。
这和scoping没有关系。
C++的lambda就可以选择capture by copy或者capture by reference. 根据之前阅读Python源码的经验(如果记错请指正),在题主的例子里面,这个inner是一个闭包。闭包在Python里面的实现方式是保存一个通往外部namespace的指针(可以理解成一个dictionary)。

楼主可以参看这个例子

  def   foo  (): 
	 def   inner  (): 
		 return   x   +   1 
	 x   =   1 
	 print   inner  ()   # output 2 
	 x   =   2 
	 print   inner  ()   # output 3 
  

这分明就是lexical scoping嘛,譬如说等价的C#代码


  void   Foo  () 
 { 
     int   x  =  1  ; 
     Func    int  >   inner   =   ()=>  x  +  1  ; 
     x  =  3  ; 
     Console  .  WriteLine  (  inner  ()); 
 } 
  
把楼主的代码改写成 lua 可以看看 Python 和 Lua 在处理上的不同:

第一个例子结果都是一样的,因为变量绑定的是引用而不是值。第二个例子:

  function   foo  () 
	 function   inner  () 
		 return   x   +   1 
	 end 
	 local   x   =   3 
	 print  (  inner  ()) 
 end 

 foo  () 
  
题主所说的 现代化的编程语言指的是什么? js经过这么多代的更新迭代,现在也是这样~

  (  function   foo  ()   { 
   function   inner  ()   { 
     return   x  +  1  ; 
   } 
   x   =   3  ; 
   console  .  log  (  inner  ()); 
 })(); 
  

  def   foo  (): 
     x   =   1 
     def   inner  (): 
         return   x   +   1 
     x   =   3 
     print   inner  () 
 foo  ()   
 #  
输出4 我觉得完全没有背离啊。。
输出感觉当前 x 走的 這個問題很好回答:x是inner函數的環境變量,所以在inner的定義中出現的x其實就是對定義外面的,也就是inner的環境變量的一個引用而已。

函數只有在被調用的時候才會執行,你前面將置為1,後面又改為3,不過是改變了x的引用值而已,相當於給x重新賦值。然後執行inner函數,使用x所對應的值為3,因此答案就是4了。

查看更多关于为什么Python不是lexicalscoping?的详细内容...

  阅读:34次