注意for迴圈中變數的作用域

高洛峰
發布: 2016-10-18 09:16:47
原創
1847 人瀏覽過

for e in collections:
    pass
登入後複製

在for 迴圈裡, 最後一個物件e一直存在在上下文中。就是在循環外面,接下來對e的引用仍然有效。

這裡有個問題容易被忽略,如果在循環之前已經有一個同名物件存在,這個物件是被覆蓋的。

如果在有程式碼感知的IDE中, IDE會提示變數是“重新宣告的”, 但執行時卻不會出錯。

for循環不是閉包,可以使用dis模組分解以下程式碼可以看到:

x = 5
for x in range(10):
    pass
print x
登入後複製

將程式碼儲存到test.py文件,執行python -m dis test.py


C:UserPatrick python -m dis test.py

  1           0 LOAD_CONST               0 (5)?    0 (x)


  3           6 SETUP_LOOP                          1 (range)

             12 LOAD_CONST            12 LOAD_CONST              (10)

             15 CALL_FUNCTION            1

     TER                 6 (to 28)

             22 STORE_NAME             25 JUMP_ABSOLUTE           19

        >>   28 POP_BLOCK

  6     >>   29 LOAD_NAME                0 (x)


       _NEWLINE

             34 LOAD_CONST               2 (None)

🎝是可見的,例如java, 因為java是強型別的語言, 如果重新宣告已存在的變數IDE會提示錯誤, 當然不同透過編譯。

通常在python程式設計中(可能是大多數的動態語言),有時即使聲明了同名的變量,程式沒有出現明顯的錯誤,但是一旦出錯,錯誤很難被發現。所以要避免與for迴圈中的變數重名。


在使用python模板語言編碼時尤其如此。程式碼編輯器沒有提示,不會發現錯誤在哪裡。這個是我碰到的極度怪異的例子。為什麼說怪異,因為邏輯上沒有任何問題。

在一個頁面模板裡面,當handler調用這個模板時,同時傳遞了兩個物件(從handler中,我使用tornado),一個page物件和一個pages列表。我的順序是這樣的:

{{ page.name if page else ''}}

🎝 %}

            {% for page in pages%}

           

{{page.name}}

            

None

   

{{ page.markdown if page else ''}}

問題來了,在運行的時候出錯了,提示在

{{ page.name if page else ''}}

中錯誤page referenced before assignment.

暈死了, 找了一夜的錯,最後在把for循環中page的名字改為_page才運行了。

在模板呼叫過程裡,模板語言也是被翻譯到python字節碼,並且按行解析和出,所以根本沒有邏輯,不知道是tornado模板語言的bug。 所以注意變數名。

總之我認為tornado的exception trace非常不友善。

Python中變數的作用域搜尋順序:本地作用域(Local)→目前作用域被嵌入的本地作用域(Enclosing locals)→全域/模組作用域(Global)→內建作用域(Built-in)

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!