這似乎背離了現代程式設計語言的一般設計思路。
比如
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而不是1echo $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 + 1x = 1print inner() # output 2x = 2print 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 + 1endlocal x = 3print(inner())endfoo()
題主所說的 現代化的程式設計語言指的是什嗎? 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了。