搜索
Table_bottom

标签云
Table_bottom

分类
Table_bottom

声明
文章若未特別註明,皆採用 知识共享许可协议 請自覺遵守
Table_bottom

鏈。。。
Table_bottom

存档
Table_bottom

匆匆过客
88833
Table_bottom

功能
Table_bottom

Python中經驗致誤處

豫:這是一篇記述自己學藝不精的文章,而不是介紹什麼奇技淫巧或是隱藏語義的。

 

Python用了也有幾個年頭了(雖然並不是全年都在用),然而發現自己還是有很多依賴(其他語言的)經驗而導致問題的地方。可能是由於自己的學習方式,也可能僅僅是由於語義的問題,這些問題也許是一些人學習中總是會遇到的(嗯,我不會說有一些同學也遇到這些問題),故且總結一下,以饗後人。

 

我個人學習Python所依賴的是:1.其他語言的經驗(Pascal/C/C++/Java);2.實踐;3.《Python學習手冊》。

是的,我沒有看《Python Cookbook》一類的(貌似更適合用來入門的)東西——不是因爲覺得沒必要,而是因爲不知道《Python學習手冊》裏邊的內容居然是那個樣子……而看完《Python學習手冊》以後就再也不想看什麼書了,實在是被它的厚度噁心到了。

 

函數參數默認值

Python中支持函數重載,也(因此而得以)支持參數默認值。

在最初用過的其他語言中,一些(C、Java)不支持重載,而支持的(C++)也沒有內置一些高級數據結構(及其便捷的初始化方法),於是從來沒有遇到過這種問題。

 

到了Python中,我想當然地以爲:參數默認值在每次函數調用的時候都是一個全新的,或者說每次重入的時候都會重新初始化一遍。

而事實上,參數默認值在每次重入時都是同一個!

 

這在簡單一些的數據結構中問題/區別不大,例如數字等不可變類型:因爲它們每次賦值時都會修改引用爲一個新的,而不是修改目標數據的值。

然而,遇到複雜數據結構/對象的時候,區別就體現出來了。我碰到的就是以一個空列表(list)爲默認值時產生的奇妙現象:在函數中每次都要修改這個列表,而由於總是同一個對象,而不是每次從一個空白的新對象開始,於是進行索引、追加等等操作時候結果總是和預期的不同。

 

意識到這個問題之後開始排查問題所在,最終鎖定到參數默認值上。經過一段搜索,搜到了這裏。其中解釋道:參數默認值僅僅在def語句被執行時會被求值。並且,其中也給出了替代的解決方案,如:使用None作爲默認值,之後在函數體中進行判斷。

 

變量作用域

按照C++的習慣,每一個區塊中的變量在出了區塊之後就失效——其中用花括號({})來界定區塊。

故而,在python中我一直以爲每個縮進層級中所創建的變量在出了該層級之後就失效。

然而在教人(之前從沒學過編程)Python時,發現居然不是這樣!當時還鬧了個笑話……

 

所以看來Python中變量作用域是整個函數,而不僅僅是聲明/賦值的那個區塊。

 

import入口

寫的某個flask程序中由於需要在整個程序中共享一些變量/對象,所以在入口的最外區塊中直接進行賦值,然後在其他部分import之。

看起來一直運行正常,然而在假如migrate的時候出事了,數據庫ORM沒有出現。排查好久終於通過id()發現其他部分所用的變量和入口處的那個不同,而它們之間相同……

於是纔意識到,入口的那些代碼在調用的時候執行一次,在import時候又執行一次,而反復import的時候不會重複執行。

是了,以前只知道反復import不會重複執行,但是從來沒意識到入口處並不是import的……

 

 

(主作於2016.3.15。拖延症……)