既然清楚 了什么是元类,就有一个相关的概念,我一直在使用它,却不知道它的真正含义。
我想每个人都犯过一次括号错误,导致“对象不可调用”异常。更重要的是,使用 __init__
和 __new__
让人想知道这个该死的 __call__
能用来干什么。
你能给我一些解释,包括魔术方法的例子吗?
原文由 e-satis 发布,翻译遵循 CC BY-SA 4.0 许可协议
来自 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。签名与 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')
原文由 jfs 发布,翻译遵循 CC BY-SA 3.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
2 回答850 阅读✓ 已解决
1 回答1.7k 阅读✓ 已解决
可调用对象是任何可以调用的对象。
内置 可调用 对象(objects.c 中的 PyCallable_Check) 检查参数是否为:
__call__
方法的类的实例或名为
__call__
的方法是( 根据文档)例子