![](/img/trans.png)
[英]Get the name of the python 3.x method that was called inside of __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
。 除了速度問題之外還有幾點:
try... except TypeError
有問題: TypeError
有時可能被其他東西引發。 例如,如果您成功調用了一個在其正文中引發TypeError
的函數,則except
將錯誤地捕獲該函數並假設該對象不可調用。 __getattr__
,可能導致hasattr
出錯。 collections.abc.Callable
似乎是一個非常重的機器,對於這么簡單的東西。 畢竟, callable
做同樣的工作。 腳注:對於這類事情, try
塊在Python中是一種非常常見的模式 ,因此您可能會在其他人的代碼中看到很多這樣的模式。 但是,正如我上面所概述的那樣,這是一個不太適合的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.