现在,元类是什么已经很清楚了,有一个相关的概念,我一直在使用,但不知道它的真正含义。
我想每个人都犯过一次圆括号错误,导致“对象不可调用”异常。更重要的是,使用__init__和__new__会导致想知道这个该死的__call__可以用来做什么。
你能给我一些解释吗,包括魔术方法的例子?
现在,元类是什么已经很清楚了,有一个相关的概念,我一直在使用,但不知道它的真正含义。
我想每个人都犯过一次圆括号错误,导致“对象不可调用”异常。更重要的是,使用__init__和__new__会导致想知道这个该死的__call__可以用来做什么。
你能给我一些解释吗,包括魔术方法的例子?
当前回答
在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
其他回答
Callable是一个具有__call__方法的对象。这意味着你可以伪造可调用的函数,或者做一些简单的事情,比如Partial Function Application,你可以取一个函数,添加一些增强它的东西,或者填充一些参数,返回一些可以依次调用的东西(在函数编程圈中称为curiling)。
某些排版错误会使解释器试图调用一些您不打算调用的东西,例如字符串。这可能会在解释器试图执行不可调用的应用程序时产生错误。你可以在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属性一样。函数和类一样都是可调用的,类实例也是可调用的。看这里和这里。
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
>>>
可调用对象是允许您使用圆括号()并最终传递一些参数的对象,就像函数一样。
每次定义函数时,python都会创建一个可调用对象。 例如,你可以用这些方式定义函数func(它们是一样的):
class a(object):
def __call__(self, *args):
print 'Hello'
func = a()
# or ...
def func(*args):
print 'Hello'
你可以使用这个方法而不是doit或run方法,我认为obj()比obj.doit()更清楚。
让我反过来解释:
考虑这个……
foo()
... 作为语法上的糖:
foo.__call__()
其中foo可以是任何响应__call__的对象。当我说任何对象时,我指的是内置类型,你自己的类和它们的实例。
对于内置类型,当你写:
int('10')
unicode(10)
你实际上是在做:
int.__call__('10')
unicode.__call__(10)
这也是Python中没有foo = new int的原因:你只需要让类对象在__call__上返回它的一个实例。在我看来,Python解决这个问题的方式非常优雅。