现在,元类是什么已经很清楚了,有一个相关的概念,我一直在使用,但不知道它的真正含义。
我想每个人都犯过一次圆括号错误,导致“对象不可调用”异常。更重要的是,使用__init__和__new__会导致想知道这个该死的__call__可以用来做什么。
你能给我一些解释吗,包括魔术方法的例子?
现在,元类是什么已经很清楚了,有一个相关的概念,我一直在使用,但不知道它的真正含义。
我想每个人都犯过一次圆括号错误,导致“对象不可调用”异常。更重要的是,使用__init__和__new__会导致想知道这个该死的__call__可以用来做什么。
你能给我一些解释吗,包括魔术方法的例子?
当前回答
可调用对象是允许您使用圆括号()并最终传递一些参数的对象,就像函数一样。
每次定义函数时,python都会创建一个可调用对象。 例如,你可以用这些方式定义函数func(它们是一样的):
class a(object):
def __call__(self, *args):
print 'Hello'
func = a()
# or ...
def func(*args):
print 'Hello'
你可以使用这个方法而不是doit或run方法,我认为obj()比obj.doit()更清楚。
其他回答
Callable是带有方法的“内置函数或方法”的类型或类 调用
>>> type(callable)
<class 'builtin_function_or_method'>
>>>
例子: Print是一个可调用对象。使用内置函数调用 当你调用print函数时,Python创建一个print类型的对象,并调用它的方法调用,如果有参数,则传递参数。
>>> type(print)
<class 'builtin_function_or_method'>
>>> print.__call__(10)
10
>>> print(10)
10
>>>
你可以在它后面加上“(args)”,并期望它能工作。可调用对象通常是一个方法或类。方法被调用,类被实例化。
来自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
tp_call字段说明:
ternaryfunc tp_call可选 指向实现的函数的指针 调用对象。这应该是 如果对象不可调用,则为NULL。 签名与for相同 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')
Callable是一个具有__call__方法的对象。这意味着你可以伪造可调用的函数,或者做一些简单的事情,比如Partial Function Application,你可以取一个函数,添加一些增强它的东西,或者填充一些参数,返回一些可以依次调用的东西(在函数编程圈中称为curiling)。
某些排版错误会使解释器试图调用一些您不打算调用的东西,例如字符串。这可能会在解释器试图执行不可调用的应用程序时产生错误。你可以在python解释器中看到这种情况,方法是执行下面的脚本。
[nigel@k9 ~]$ python
Python 2.5 (r25:51908, Nov 6 2007, 15:55:44)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'aaa'() # <== Here we attempt to call a string.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>>
__call__使任何对象都可以作为函数调用。
这个例子将输出8:
class Adder(object):
def __init__(self, val):
self.val = val
def __call__(self, val):
return self.val + val
func = Adder(5)
print func(3)