什么是“可调用的”?

现在什么是元类很清楚了,有一个相关的概念,我一直在使用,但不知道它的真正含义。

我想每个人都犯过一次圆括号错误,导致“对象不可调用”异常。更重要的是,使用__init____new__会导致想知道这个该死的__call__可以用来做什么。

你能给我一些解释吗,包括魔术方法的例子?

327577 次浏览

Callable是一个具有__call__方法的对象。这意味着你可以伪造可调用的函数,或者做一些整洁的事情,比如部分函数应用,你取一个函数并添加一些增强它的东西或填充一些参数,返回可以依次调用的东西(在函数式编程圈中称为局部套用)。

某些排版错误会使解释器试图调用一些您不打算调用的东西,例如字符串。这可能会在解释器试图执行不可调用的应用程序时产生错误。你可以在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
>>>

很简单,“可调用对象”是可以像方法一样调用的对象。内置函数"callable()"将告诉你某个东西是否看起来是可调用的,检查调用属性也是如此。函数和类一样都是可调用的,类实例也是可调用的。请参阅有关在这里在这里的更多信息。

你可以在它后面加上“(args)”,并期望它能工作。可调用对象通常是一个方法或类。方法被调用,类被实例化。

可调用对象是任何可以调用的对象。

内置callable (PyCallable_Check in objects.c)检查参数是否为:

  • 具有__call__方法的类的实例或
  • 是具有非空tp_call (c struct)成员的类型,该成员指示可调用性(例如在函数,方法等中)。

命名为__call__的方法是(根据文档)

当实例作为函数被“调用”时调用

例子

class Foo:
def __call__(self):
print 'called'


foo_instance = Foo()
foo_instance() #this is calling the __call__ method

__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)

在Python中,可调用对象是一个类型具有__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

就这么简单:)

这当然可以重载:

>>> class Foo(object):
...  def __call__(self):
...   return 42
...
>>> f = Foo()
>>> f()
42

来自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;
}
}

它说:

  1. 如果对象是某个类的实例,则可调用敌我识别,它具有__call__属性。
  2. 否则对象x是可调用的敌我识别 x->ob_type->tp_call != NULL

tp_call领域的描述:

ternaryfunc tp_call可选参数 指向实现的函数的指针 调用对象。这应该是 如果对象不可调用,则为NULL。 签名与for相同 PyObject_Call()。这个字段是

你总是可以使用内置的callable函数来确定给定对象是否可调用;或者更好的方法是稍后调用它并捕获TypeErrorcallable在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')

可调用对象是允许您使用圆括号()并最终传递一些参数的对象,就像函数一样。

每次定义函数时,python都会创建一个可调用对象。 例如,你可以用以下方式定义函数函数(它们是一样的):

class a(object):
def __call__(self, *args):
print 'Hello'


func = a()


# or ...
def func(*args):
print 'Hello'

你可以使用这个方法而不是doit运行这样的方法,我认为obj()比obj.doit()更清楚。

callables实现了__call__特殊方法,因此任何具有这种方法的对象都是可调用的。

让我反过来解释:

考虑这个……

foo()

... 作为语法上的糖:

foo.__call__()

其中foo可以是任何响应__call__的对象。当我说任何对象时,我指的是内置类型,你自己的类和它们的实例。

对于内置类型,当你写:

int('10')
unicode(10)

你实际上是在做:

int.__call__('10')
unicode.__call__(10)

这也是Python中没有foo = new int的原因:你只需让类对象返回它在__call__上的一个实例。在我看来,Python解决这个问题的方式非常优雅。

检查类的函数或方法是否可调用,这意味着我们可以调用该函数。

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是“内置函数或方法”的类型或类;用一个方法 调用< / >强

>>> type(callable)
<class 'builtin_function_or_method'>
>>>
< p >的例子: >是一个可调用对象。内置函数< >强打电话 当你调用打印函数时,Python会创建一个类型为print的对象并调用它的方法< >强打电话
(如果有参数的话)
>>> type(print)
<class 'builtin_function_or_method'>
>>> print.__call__(10)
10
>>> print(10)
10
>>>

具有__call__()的类、函数、方法和对象是可调用的

你可以用< >强可调用()< / >强检查是否可调用,如果可调用则返回True,如果不可调用则返回False,如下所示:

class Class1:
def __call__(self):
print("__call__")


class Class2:
pass


def func():
pass


print(callable(Class1))   # Class1
print(callable(Class2))   # Class2


print(callable(Class1())) # Class1 object
print(callable(Class2())) # Class2 object


print(callable(func))     # func

然后,只有没有__call__()Class2对象不可调用,返回False,如下所示:

True  # Class1
True  # Class2
True  # Class1 object
False # Class2 object
True  # func

此外,下面所有的函数都是不可调用的,返回False,如下所示:

print(callable("Hello"))  # "str" type
print(callable(100))      # "int" type
print(callable(100.23))   # "float" type
print(callable(100 + 2j)) # "complex" type
print(callable(True))     # "bool" type
print(callable(None))     # "NoneType"
print(callable([]))       # "list" type
print(callable(()))       # "tuple" type
print(callable({}))       # "dict" type
print(callable({""}))     # "set" type

输出:

False # "str" type
False # "int" type
False # "float" type
False # "complex" type
False # "bool" type
False # "NoneType"
False # "list" type
False # "tuple" type
False # "dict" type
False # "set" type