jfs..
79
从Python的源代码object.c:
/* Test whether an object can be called */
int
PyCallable_Check(PyObject *x)
{
if (x == NULL)
return 0;
if (PyInstance_Check(x)) {
PyObject *call = PyObject_GetAttrString(x, "__call__");
if (call == NULL) {
PyErr_Clear();
return 0;
}
/* Could test recursively but don't, for fear of endless
recursion if some joker sets self.__call__ = self */
Py_DECREF(call);
return 1;
}
else {
return x->ob_type->tp_call != NULL;
}
}
它说:
如果一个对象是某个类的实例,那么如果它具有__call__属性,则它是可调用的.
否则该对象x可以调用iff x->ob_type->tp_call != NULL
ternaryfunc tp_call指向实现调用对象的函数的可选指针.如果对象不可调用,则此值应为NULL.签名与PyObject_Call()相同.该字段由子类型继承.
您始终可以使用内置callable函数来确定给定对象是否可调用; 或者更好,但只是打电话给它,然后赶上TypeError.callable在Python 3.0和3.1中删除,使用callable = lambda o: hasattr(o, '__call__')或isinstance(o, collections.Callable).
例如,一个简单的缓存实现:
class Cached:
def __init__(self, function):
self.function = function
self.cache = {}
def __call__(self, *args):
try: return self.cache[args]
except KeyError:
ret = self.cache[args] = self.function(*args)
return ret
用法:
@Cached
def ack(x, y):
return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1)
标准库,文件site.py,内置函数exit()和quit()函数的示例:
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
@JF塞巴斯蒂安:这是BS,更像生活的例子更好.我可以向你展示生活般的代码,让你哭泣作为一个例子.简单的例子也可以工作,它们可以更好地说明一些东西,因为它们不会分散注意力. (19认同)
我发现__call__方法的示例极具误导性,因为它将它与缓存和装饰器的配方混合在一起,这对于__call__的理解没有任何帮助. (10认同)
您正在解释什么是可调用的,但您举例说明了如何使用可调用对象来定义装饰器.我知道这是__callable__的典型用法,但这可能会让想知道什么是可调用的读者以及如何使用__callable__的读者感到困惑.我更喜欢@FlorianBösch的回答. (5认同)
JF塞巴斯蒂安,也写了更多你从其他地方复制和粘贴的例子并没有帮助. (3认同)
@Kay:我也喜欢@FlorianBösch的答案(目前的形式).顺便说一句,装饰者不是*"可调用"的典型用法.最典型的"callables"是函数/方法,例如`def f():...`,以及类对象,例如`class C:...`ie,`f`,`''..strip`,` len`和`C`都是可调用的.在类中具有`__call __()`方法的实例相对较少. (2认同)