python 排名函数_一个危险的Python函数,不推荐使用
本文由編程派根據 Hacker News 上曾經排名第一的文章 編譯而來,作者 Hynek Schlawack 是一名德國軟件工程師。
他建議, 除非是編寫只兼容 Python 3 的代碼而且清楚地了解 hasattr() 的用法,否則不要使用 hasattr() 。
在 Python 2 下,不建議編寫這樣的代碼:
if hasattr(x, "y"):
print(x.y)
else:
print("no y!")
更好的做法是像如下兩例所示:
try:
print(x.y)
except AttributeError:
print("no y!")
或者
y = getattr(x, "y", None)
if y is not None:
print(y)
else:
print("no y!")
如果處理的不是用戶自行創建的類,更應該采用上述寫法。
上面有一處用到了 getattr() ,這里將屬性缺失視作屬性的值為 None (常見的情況),如果想與此區分開來,可使用一個標記值(sentinel value)。 getattr 的速度不比 hasattr() 低,因為二者的查找過程完全相同,并且后者不會保存結果(至少在CPython實現下是如此)。
為什么不建議使用 hasattr()
在 Python 2 下使用 hasattr() ,和下面的代碼幾乎沒有分別:
try:
print(x.y)
except:
print("no y!")
但是這樣會隱藏掉特性(property):
>>> class C(object):
... @property
... def y(self):
... 0/0
...
>>> hasattr(C(), "y")
False
對于第三方庫中類,我們無法確定某個屬性(attribute)是否為特性(或者之后某次更新將其變成特性),因此上面那樣使用 hasattr() 是非常危險的。
你或許不信,但是 Hacker News 上確實有程序員回復說經歷過這個情況, hasattr() 隱藏了一個非常深的錯誤,讓程序調式工作變得異常艱難。
另外一個原因是,對特性使用 hasttr() 會執行它們的 getter 函數,但這樣和 hasattr() 這個函數的名稱并不相符。
不過,在 Python 3 中, hasattr() 不存在這些問題:
>>> class C:
... @property
... def y(self):
... 0/0
...
>>> hasattr(C(), "y")
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in y
ZeroDivisionError: division by zero
因此,在編寫兼容 Python 2 和 3 的混合代碼時,要特別注意這個函數。另外,你應該想不到 hasattr() 會引發 ZeroDivisionError 吧?
留心的讀者可能會問,如果出現AttributeError呢??的確,如果真出現,我們沒有辦法區分到底是因為真的缺失該屬性,還是特性存在問題。 文首提到的寫法可以將可能的錯誤減少為只有一種,避免出現 Python 2 和 3 之間讓人困惑的行為差異 。.
結語
當然,在你自己寫的代碼中仍然可以使用 hasattr() ,但是 如果后來修改了類,記得也要修改對應的 hasattr() ,確保不會出錯 。不過雖然這樣可以少寫些代碼,但是卻增加了不必要的心理負擔。
總結
以上是生活随笔為你收集整理的python 排名函数_一个危险的Python函数,不推荐使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python没有指针如何实现链表_[转]
- 下一篇: 德力股份是做什么的