What is a “callable”?

前端 未结 12 2092
谎友^
谎友^ 2020-11-22 01:23

Now that it\'s clear what a metaclass is, there is an associated concept that I use all the time without knowing what it really means.

I suppose everybody made once

相关标签:
12条回答
  • 2020-11-22 01:56

    callables implement the __call__ special method so any object with such a method is callable.

    0 讨论(0)
  • 2020-11-22 01:57

    Quite simply, a "callable" is something that can be called like a method. The built in function "callable()" will tell you whether something appears to be callable, as will checking for a call property. Functions are callable as are classes, class instances can be callable. See more about this here and here.

    0 讨论(0)
  • 2020-11-22 02:01

    A callable is an object allows you to use round parenthesis ( ) and eventually pass some parameters, just like functions.

    Every time you define a function python creates a callable object. In example, you could define the function func in these ways (it's the same):

    class a(object):
        def __call__(self, *args):
            print 'Hello'
    
    func = a()
    
    # or ... 
    def func(*args):
        print 'Hello'
    

    You could use this method instead of methods like doit or run, I think it's just more clear to see obj() than obj.doit()

    0 讨论(0)
  • 2020-11-22 02:03

    From Python's sources 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;
        }
    }
    

    It says:

    1. If an object is an instance of some class then it is callable iff it has __call__ attribute.
    2. Else the object x is callable iff x->ob_type->tp_call != NULL

    Desciption of tp_call field:

    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.

    You can always use built-in callable function to determine whether given object is callable or not; or better yet just call it and catch TypeError later. callable is removed in Python 3.0 and 3.1, use callable = lambda o: hasattr(o, '__call__') or isinstance(o, collections.Callable).

    Example, a simplistic cache implementation:

    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    
    

    Usage:

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

    Example from standard library, file site.py, definition of built-in exit() and quit() functions:

    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')
    
    0 讨论(0)
  • 2020-11-22 02:05

    Let me explain backwards:

    Consider this...

    foo()
    

    ... as syntactic sugar for:

    foo.__call__()
    

    Where foo can be any object that responds to __call__. When I say any object, I mean it: built-in types, your own classes and their instances.

    In the case of built-in types, when you write:

    int('10')
    unicode(10)
    

    You're essentially doing:

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

    That's also why you don't have foo = new int in Python: you just make the class object return an instance of it on __call__. The way Python solves this is very elegant in my opinion.

    0 讨论(0)
  • 2020-11-22 02:05

    In Python a callable is an object which type has a __call__ method:

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

    As simple as that :)

    This of course can be overloaded:

    >>> class Foo(object):
    ...  def __call__(self):
    ...   return 42
    ... 
    >>> f = Foo()
    >>> f()
    42
    
    0 讨论(0)
提交回复
热议问题