345

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

我想每个人都犯了一次括号错误,导致“对象不可调用”异常。更何况,使用__init____new__导致想知道这该死的东西__call__可以用来做什么。

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

4

12 回答 12

340

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

内置的可调用对象(objects.c 中的PyCallable_Check)检查参数是否为:

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

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

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

例子

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

foo_instance = Foo()
foo_instance() #this is calling the __call__ method
于 2008-09-21T15:44:22.697 回答
91

从 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。签名与 PyObject_Call() 的签名相同。该字段由子类型继承。

您始终可以使用内置callable函数来确定给定对象是否可调用;或者更好的是只是调用它并稍后再捕获TypeErrorcallable在 Python 3.0 和 3.1 中被删除,使用callable = lambda o: hasattr(o, '__call__')or 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')
于 2008-09-22T15:04:53.733 回答
43

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

每次定义函数时,python 都会创建一个可调用对象。例如,您可以通过以下方式定义函数func(相同):

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

func = a()

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

您可以使用此方法代替doitrun之类的方法,我认为 obj() 比 obj.doit() 更清楚

于 2008-09-26T13:22:20.393 回答
39

让我倒过来解释一下:

考虑这个...

foo()

...作为语法糖:

foo.__call__()

哪里foo可以是任何响应的对象__call__。当我说任何对象时,我的意思是:内置类型、您自己的类及其实例。

对于内置类型,当您编写时:

int('10')
unicode(10)

你本质上是在做:

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

这也是您在 Python 中没有的原因foo = new int:您只需让类对象在__call__. 在我看来,Python 解决这个问题的方式非常优雅。

于 2013-03-22T23:38:33.647 回答
11

Callable 是具有该__call__方法的对象。这意味着您可以伪造可调用函数或做一些简洁的事情,例如Partial Function Application ,您可以在其中获取一个函数并添加一些增强它的东西或填充一些参数,返回一些可以依次调用的东西(在函数式编程界称为Currying)。

某些印刷错误会使解释器尝试调用您不打算调用的内容,例如(例如)字符串。这可能会在解释器尝试执行不可调用的应用程序时产生错误。您可以通过执行类似于下面的脚本的操作在 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
>>> 
于 2008-09-21T15:43:15.880 回答
10

__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)
于 2008-09-21T15:49:28.953 回答
7

很简单,“可调用”是可以像方法一样调用的东西。内置函数“callable()”将告诉您某些东西是否可以调用,以及检查调用属性。函数是可调用的,类也是可调用的,类实例也是可调用的。在此处此处查看更多信息。

于 2008-09-21T15:43:20.840 回答
6

在 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
于 2008-09-21T16:37:09.307 回答
3

这是你可以在后面加上“(args)”并期望它起作用的东西。可调用对象通常是方法或类。方法被调用,类被实例化。

于 2008-09-21T15:43:44.960 回答
3

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

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
于 2016-09-20T10:03:37.330 回答
2

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

于 2012-05-07T21:40:12.383 回答
0

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
>>>
于 2017-04-07T07:10:48.257 回答