簡體   English   中英

使用callable(x)vs。hasattr(x,“__ call__”)

[英]Using callable(x) vs. hasattr(x, “__call__”)

我正在編寫針對3.2及更高版本的Python。 看起來使用內置函數callable是最簡單有效的方法。 我已經看到了對hasattr(x, "__call__") call hasattr(x, "__call__")collections.Callable(x) ,並且只是在嘗試調用時使用了try/except

我已經測試了可調用的項目(類和函數),使用100,000次迭代的timeit ; 在兩種情況下,使用callable只需要檢查屬性的大約75%的時間。 當項目不可調用(整數和字符串)時,使用與類或函數相同的可調用停留時,檢查屬性的價格比類或函數貴2.3倍。 我沒想到會有這種差異,但它也有利於清晰簡潔的callable(x)方法。

但我相對較新的Python而且沒有專家,所以我不知道我應該使用hasattr方法或其他方法嗎?

FWIW,各種時間的結果如下。 第一個字符只是t表示timeit,第二個字符表示被測對象的類型(c = class,f = function,i = integer,s = string),其余表示方法(attr-check屬性, call - use callable,try - use try / except)。

tcattr 0.03665385400199739
tccall 0.026238360142997408
tctry 0.09736267629614304
tfattr 0.03624538065832894
tfcall 0.026362861895904643
tftry 0.032501874250556284
tiattr 0.08297350149314298
ticall 0.025826044152381655
titry 0.10657657453430147
tsattr 0.0840187013927789
tscall 0.02585409547373274
tstry 0.10742772077628615

hasattr()將返回比callable更多的誤報:

>>> class X(object):
...     def __getattr__(self, name):
...         return name
...
>>> i = X()
>>> from collections import Callable
>>> isinstance(i, Callable)
False
>>> callable(i)
False
>>> hasattr(i, '__call__')
True
>>> i()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'X' object is not callable

我不確定你測試的是哪個callable ,但兩者看起來都比hasattr好,處理更多的情況,所以我會用它們代替hasattr()

callable不僅是最快的,而且Zen提供了四個更重要的原因來使用它而不是其他兩個裝置:

美麗勝過丑陋。
顯式優於隱式。
簡單比復雜更好。
可讀性很重要。

好問題! 我會說你應該使用callable 除了速度問題之外還有幾點:

  1. 它明確,簡單,清晰,簡潔,整潔。
  2. 它是一個內置的Python,所以任何不知道它做什么的人都可以輕松找到。
  3. try... except TypeError有問題: TypeError有時可能被其他東西引發。 例如,如果您成功調用了一個在其正文中引發TypeError的函數,則except將錯誤地捕獲該函數並假設該對象不可調用。
  4. 一些常見的自定義,如__getattr__ ,可能導致hasattr出錯。
  5. collections.abc.Callable似乎是一個非常重的機器,對於這么簡單的東西。 畢竟, callable做同樣的工作。

腳注:對於這類事情, try塊在Python中是一種非常常見的模式 ,因此您可能會在其他人的代碼中看到很多這樣的模式。 但是,正如我上面所概述的那樣,這是一個不太適合的情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM