什么是Python中的“可调用”?

既然已经清楚元类是什么 ,那么我总是会使用一个相关的概念,而不知道它的真正含义。

我想每个人都用括号犯了一个错误,导致一个“对象不可调用”的例外。 更重要的是,使用__init____new__会导致想知道这个血腥的__call__可以用于什么。

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

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

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

  • 具有__call__方法或类的类的实例
  • 是一个具有非空tp_call (c结构)成员的类型,否则指示可调用性(例如在函数,方法等中)

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

当实例被调用为函数时调用

 class Foo: def __call__(self): print 'called' foo_instance = Foo() foo_instance() #this is calling the __call__ method 

从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可调用iff 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__')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会创建一个可调用的对象。 在例子中,你可以用这些方法定义函数func (它是一样的):

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

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

让我解释一下:

考虑这个…

 foo() 

…作为语法糖用于:

 foo.__call__() 

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

在内置类型的情况下,当你写:

 int('10') unicode(10) 

你基本上在做:

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

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

Callable是具有__call__方法的对象。 这意味着你可以伪造可调用的函数,或者做一些整洁的事情,比如部分函数应用 ,你可以在其中添加一些增强或填充某些参数的东西,然后返回一些可以依次调用的东西(在函数式编程循环中称为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 >>> 

很简单,“可调用”是可以被称为方法的东西。 内置函数“callable()”会告诉你是否有东西看起来是可调用的,就象检查一个调用属性一样。 函数可以像类一样调用,类实例可以被调用。 在这里和这里查看更多信息。

__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 

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

 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__特殊方法,因此具有这种方法的任何对象都可以调用。

可调用是一种类型或类的“内置函数或方法”与方法调用

 >>> type(callable) <class 'builtin_function_or_method'> >>> 

例如: print是一个可调用的对象。 使用内建函数__call__当您调用打印函数时,Python将创建一个print类型对象并调用其方法__call__传递参数(如果有的话)。

 >>> type(print) <class 'builtin_function_or_method'> >>> print.__call__(10) 10 >>> print(10) 10 >>> 

谢谢。 问候,Maris

找出一个对象是可调用的或不试试这个

 x=234 for i in dir(x): if i.startswith("__call__"): print i 

这里没有输出。

 def add(x,y): return x+y for i in dir(add): if i.startswith("__call__"): print i >>>__call__