溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中常見的陷阱有哪些

發(fā)布時間:2020-08-04 09:49:54 來源:億速云 閱讀:199 作者:清晨 欄目:編程語言

這篇文章主要介紹Python中常見的陷阱有哪些,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

Python的編碼規(guī)范基本遵從PEP8準則,使用四個空格作為縮進,避免空格鍵和tab鍵混用,善于添加注釋,當一行代碼寫不下時,右括號要放到行首,和變量對齊,導入順序 標準庫、第三方、本地庫,各組之間有個空行隔開。通常,Python 旨在成為一門簡潔一致的語言,避免發(fā)生意外。然而,有些情況可能會給新手們造成困惑。

在這些情況中,有一些雖是有意為之,但還是有潛在風險。還有一些則可以說是語言設(shè)計缺陷了??傊旅媪谐龅倪@些情況都是些乍一看很不好理解的行為,不過一旦您了解了這些奇怪行為背后的機理,也就基本上能理解了。

可變默認參數(shù)

似乎每個 Python 新手都會感到驚訝的一點是 Python 在函數(shù)定義中對待可變默認參數(shù)的方法。

您所寫的

def append_to(element, to=[]):
    to.append(element)
    return to

您可能期待的結(jié)果

my_list = append_to(12)
print my_list

my_other_list = append_to(42)
print my_other_list

函數(shù)每次被調(diào)用時,如果不提供第二個參數(shù),就創(chuàng)建一個新的列表。所以結(jié)果就應(yīng)該是:

[12]
[42]

實際上的結(jié)果

[12]
[12, 42]

一旦 完成了函數(shù)定義,一個新的列表就創(chuàng)建出來了,而且在隨后的每一次函數(shù)調(diào)用中被使用的都是這個列表。

一旦 完成了函數(shù)定義,Python 的默認參數(shù)就被賦值了,而且在隨后的每一次函數(shù)調(diào)用中都不會再被默認值重復(fù)賦值(就像是在,嗯,Ruby 里那樣)。這就意味著如果您使用了一個可變默認參數(shù),并且改變了它,您也會且 將會 在未來的所有函數(shù)調(diào)用中改變這同一個參數(shù)對象。

您實際上應(yīng)該做的

使用一個默認值來表示我們并不想給這個參數(shù)賦值,從而每次在函數(shù)被調(diào)用時我們都創(chuàng)建一個新的對象。(None 作為默認值通常是個好選擇)。

def append_to(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

可別忘了,您所傳遞的第二個參數(shù)仍應(yīng)該是個 列表 對象。

利用好『缺陷』

有時你可以專門 利用(或者說特地使用)這種行為來維護函數(shù)調(diào)用間的狀態(tài)。這通常用于編寫緩存函數(shù)。

延遲綁定閉包

另一個常見的困惑是 Python 在閉包(或在周圍全局作用域)中綁定變量的方式。

當你寫下

def create_multipliers():
    return [lambda x : i * x for i in range(5)]

你期望發(fā)生

for multiplier in create_multipliers():
    print multiplier(2)

一個包含五個函數(shù)的列表,每個函數(shù)有它們自己的封閉變量 i 乘以它們的參數(shù),得到:

0
2
4
6
8

而事實是:

8
8
8
8
8

五個函數(shù)被創(chuàng)建了,它們?nèi)加?4 乘以 x 。

Python 的閉包是 延遲綁定的 。 這意味著閉包中用到的變量的值,是在內(nèi)部函數(shù)被調(diào)用時查詢得到的。

這里,不論 任何 返回的函數(shù)是如何被調(diào)用的, i 取的是調(diào)用時周圍作用域里的值。 當循環(huán)完成時, i 的值最終變成了 4。

關(guān)于這個陷阱有一個普遍嚴重的誤解,它被認為只針對 Python 的 閉包 lambda 定義方式。 事實上,由 lambda 表達式創(chuàng)建的函數(shù)并沒什么特別,同樣的問題也出現(xiàn)在使用普通的 def 上:

def create_multipliers():
    multipliers = []

    for i in range(5):
        def multiplier(x):
            return i * x
        multipliers.append(multiplier)

    return multipliers

以上正確的做法應(yīng)該是:

def create_multipliers():
    return [lambda x, i=i : i * x for i in range(5)]

或者,使用 functools.partial 函數(shù):

from functools import partial
from operator import mul

def create_multipliers():
    return [partial(mul, i) for i in range(5)]

有時你就想要閉包有如此表現(xiàn),延遲綁定在很多情況下是一個很贊的特性。不幸的是,循環(huán)創(chuàng)建獨立函數(shù)是一種會使它們出差錯的情況。

字節(jié)碼(.pyc)文件無處不在!

默認情況下,當你直接執(zhí)行 Python 腳本文件時,Python 解釋器會自動將該文件的字節(jié)碼版本寫入同目錄下。 比如, module.pyc。

這些 .pyc 文件不應(yīng)該被納入源代碼倉庫。

理論上,出于性能原因,此行為默認為開啟。 沒有這些字節(jié)碼文件, Python 會在每次加載文件時重新生成字節(jié)碼文件。

禁用字節(jié)碼(.pyc)文件

幸運的是,生成字節(jié)碼的過程非???,在開發(fā)代碼時不需要擔心。

那些文件很討厭,所以讓我們擺脫他們吧!

$ export PYTHONDONTWRITEBYTECODE=1

使用 $PYTHONDONTWRITEBYTECODE 環(huán)境變量來命令 Python 不將這些文件寫入磁盤, 開發(fā)環(huán)境將會保持整潔和干凈。

我建議在你的 ~/.profile 里設(shè)置這個環(huán)境變量。

以上是Python中常見的陷阱有哪些的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI