什么是“可呼叫”?

2024-04-24 22:17:59 发布

您现在位置:Python中文网/ 问答频道 /正文

既然已经清楚了what a metaclass is,有一个相关的概念我一直在使用,却不知道它的真正含义。

我想每个人都会犯一次括号错误,导致“objectisnotcallable”异常。更重要的是,使用__init____new__会让人怀疑这个该死的__call__可以用来做什么。

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


Tags: 方法概念newinitis错误魔法call
3条回答

从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. 如果一个对象是某个类的实例,那么它可以调用iff它有__call__属性。
  2. 否则对象x可调用iffx->ob_type->tp_call != NULL

^{} 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.

您始终可以使用内置的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) 

来自标准库、文件^{}、内置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')

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

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

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

func = a()

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

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

可调用的就是任何可以调用的东西。

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

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

名为__call__的方法是(according to the documentation

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

示例

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

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

相关问题 更多 >