现在很明显what a metaclass is,我总是使用一个相关的概念而不知道它的真正含义。
我想每个人都用括号做错了,导致“对象不可调用”异常。更重要的是,使用__init__
和__new__
导致想知道这个血腥的__call__
可以用于什么。
你能给我一些解释,包括魔术方法的例子吗?
可调用是可以调用的任何东西。
built-in callable (PyCallable_Check in objects.c)检查参数是否为:
名为__call__的方法是(according to the documentation)
当实例被“调用”为函数时调用
class Foo:
def __call__(self):
print 'called'
foo_instance = Foo()
foo_instance() #this is calling the __call__ method
检查类的函数或方法是否可调用,这意味着我们可以调用该函数。
>>> class Foo(object):
... def __call__(self):
... return 42
...
>>> f = Foo()
>>> f()
42
callables实现了Class A:
def __init__(self,val):
self.val = val
def bar(self):
print "bar"
obj = A()
callable(obj.bar)
True
callable(obj.__init___)
False
def foo(): return "s"
callable(foo)
True
callable(foo())
False
特殊方法,因此具有这种方法的任何对象都是可调用的。
Callable是一种带有方法调用的“内置函数或方法”的类型或类
__call__
示例:print是可调用对象。使用内置函数__call__当您调用print函数时,Python会创建一个print类型的对象,并调用其方法__call__传递参数(如果有)。
>>> type(callable)
<class 'builtin_function_or_method'>
>>>
谢谢。此致,Maris
来自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
可以调用qazxsw poi的描述:
tp_call
field指向实现调用对象的函数的可选指针。如果对象不可调用,则此值应为NULL。签名与PyObject_Call()相同。该字段由子类型继承。
您始终可以使用内置的ternaryfunc tp_call
函数来确定给定对象是否可调用;或者更好,然后再打电话,然后赶上callable
。在Python 3.0和3.1中删除TypeError
,使用callable
或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()
可调用对象允许您使用圆括号()并最终传递一些参数,就像函数一样。
每次定义函数时,python都会创建一个可调用对象。在示例中,您可以通过以下方式定义函数func(它是相同的):
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')
您可以使用此方法而不是像doit或run这样的方法,我认为看到obj()比obj.doit()更清楚
让我向后解释:
考虑一下......
class a(object):
def __call__(self, *args):
print 'Hello'
func = a()
# or ...
def func(*args):
print 'Hello'
...作为语法糖:
foo()
foo.__call__()
可以是任何响应foo
的物体。当我说任何对象时,我的意思是:内置类型,你自己的类和它们的实例。
在内置类型的情况下,当你写:
__call__
你基本上是这样做的:
int('10')
unicode(10)
这也是你在Python中没有int.__call__('10')
unicode.__call__(10)
的原因:你只需让类对象在foo = new int
上返回它的一个实例。在我看来,Python解决这个问题的方式非常优雅。
Callable是一个具有__call__
方法的对象。这意味着你可以伪造可调用的函数或做一些像__call__
这样的东西,你可以在这里添加一个函数并添加一些东西来增强它或填充一些参数,返回可以依次调用的东西(在函数式编程循环中称为Partial Function Application)。
某些排版错误会使解释程序尝试调用您不想要的内容,例如(例如)字符串。这可能会在解释器尝试执行不可调用的应用程序时产生错误。您可以通过执行类似下面的脚本的操作在python解释器中看到这种情况。
Currying
很简单,“可调用”是可以像方法一样调用的东西。内置函数“callable()”将告诉您某些内容是否可以调用,以及检查调用属性。函数可以像类一样调用,类实例可以调用。查看有关此[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
>>>
和here的更多信息。
在Python中,callable是一个类型具有class Adder(object):
def __init__(self, val):
self.val = val
def __call__(self, val):
return self.val + val
func = Adder(5)
print func(3)
方法的对象:
__call__
就如此容易 :)
这当然可以重载:
>>> class Foo:
... pass
...
>>> class Bar(object):
... pass
...
>>> type(Foo).__call__(Foo)
<__main__.Foo instance at 0x711440>
>>> type(Bar).__call__(Bar)
<__main__.Bar object at 0x712110>
>>> def foo(bar):
... return bar
...
>>> type(foo).__call__(foo, 42)
42
这是你可以把“(args)”放在后面并期望它起作用的东西。可调用通常是方法或类。方法被调用,类被实例化。