关于Python:什么是”可调用”“callable”?

What is a “callable”?

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

我想每个人都犯过一次括号错误,导致了"object is not called"异常。更重要的是,使用__init____new__会让人怀疑这种血淋淋的__call__能做什么。

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


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

内置可调用(pycallable_check in objects.c)检查参数是否为:

  • 类的一个实例,具有一个调用方法或
  • 属于具有非空tp_调用(c struct)成员的类型,该成员以其他方式指示可调用性(如在函数、方法等中)。

名为"call"的方法是(根据文档)

Called when the instance is ''called'' as a function

例子

1
2
3
4
5
6
class Foo:
  def __call__(self):
    print 'called'

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


从python的sources对象.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 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 An optional
    pointer to a function that implements
    calling the object. This should be
    NULL if the object is not callable.
    The signature is the same as for
    PyObject_Call(). This field is
    inherited by subtypes.

    您可以始终使用内置的callable函数来确定给定对象是否可调用;或者更好的方法是稍后调用它并捕获TypeError。在python 3.0和3.1中删除callable,使用callable = lambda o: hasattr(o, '__call__')isinstance(o, collections.Callable)

    例如,一个简单的缓存实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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

    用途:

    1
    2
    3
    @Cached
    def ack(x, y):
        return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1)

    标准库示例,文件site.py,内置exit()quit()函数的定义:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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都会创建一个可调用对象。在示例中,可以通过以下方式定义函数func(它是相同的):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class a(object):
        def __call__(self, *args):
            print 'Hello'

    func = a()

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

    您可以使用这个方法,而不是像doit或run这样的方法,我认为看到obj()比obj.doit()更清楚。


    让我反向解释一下:

    考虑一下……

    1
    foo()

    …作为句法的糖分:

    1
    foo.__call__()

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

    对于内置类型,在编写时:

    1
    2
    int('10')
    unicode(10)

    你基本上是在做:

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

    这也是为什么在python中没有foo = new int:您只是让类对象在__call__上返回它的一个实例。在我看来,python解决这个问题的方法非常优雅。


    可调用对象是具有__call__方法的对象。这意味着你可以伪造可调用函数,或者做一些简单的事情,比如部分函数应用程序,在那里你得到一个函数并添加一些增强它的东西或者填充一些参数,然后返回一些可以依次调用的东西(在函数编程循环中称为curring)。

    某些排版错误会让解释器尝试调用您不希望调用的内容,例如字符串。当解释器尝试执行不可调用的应用程序时,这可能会产生错误。您可以在python解释器中通过执行下面的脚本之类的操作看到这种情况。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [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()"将告诉您某个东西是否看起来是可调用的,检查call属性也是如此。函数和类一样可以调用,类实例也可以调用。在这里和这里了解更多关于这个的信息。


    __call__使任何对象都可以作为函数调用。

    此示例将输出8:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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__方法的对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    >>> 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

    就这么简单:)

    这当然可以超载:

    1
    2
    3
    4
    5
    6
    7
    >>> class Foo(object):
    ...  def __call__(self):
    ...   return 42
    ...
    >>> f = Foo()
    >>> f()
    42

    可调用是"内置函数或方法"的类型或类,具有一个方法呼叫

    1
    2
    3
    >>> type(callable)
    <class 'builtin_function_or_method'>
    >>>

    例子:print是一个可调用的对象。具有内置函数uuu调用__当您调用print函数时,python创建一个print类型的对象,并调用它的方法,调用传递参数(如果有的话)。

    1
    2
    3
    4
    5
    6
    7
    >>> type(print)
    <class 'builtin_function_or_method'>
    >>> print.__call__(10)
    10
    >>> print(10)
    10
    >>>

    谢谢您。当做,马里斯


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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


    你可以把它放在(args)之后,期望它能工作。可调用通常是一个方法或类。方法被调用,类被实例化。


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