当前位置:  开发笔记 > 编程语言 > 正文

什么是Python中的"可调用"?

如何解决《什么是Python中的"可调用"?》经验,为你挑选了8个好方法。

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

我想每个人都用括号做错了,导致"对象不可调用"异常.更重要的是,使用__init____new__导致想知道这种血腥__call__可以用于什么.

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



1> Florian Bösc..:

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

所述内置的可调用(PyCallable_Check在objects.c)检查该参数可以是:

带有__call__方法或类的类的实例

是一种具有非null tp_call(c struct)成员的类型,否则表示可调用性(例如在函数,方法等中)

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

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

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

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


@Longpoke:只是为了记录,请参阅[Python 3.x中`callable()`的文档](http://docs.python.org/3/library/functions.html#callable):"_这个函数首先在Python 3.0中删除,然后在Python 3.2._中恢复."
@Eli:嗯,这听起来像是一个非常糟糕的举动.`callable`实际上告诉你是否可以调用某些东西,而检查`__call__`什么都不告诉你; 如果对象`o`提供`__getattribute__`或`__getattr__`,`hasattr(o,'__ call __')`可能返回True,但是`o`仍然不可调用,因为Python跳过`__getattribute__`和`__getattr__`进行调用.因此,EAFP是唯一能够检查某些东西是否可调用的真正方法.
请注意,在Python 3.0中删除了内置可调用对象,以支持检查__call__

2> jfs..:

从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;
    }
}

它说:

    如果一个对象是某个类的实例,那么如果它具有__call__属性,则它是可调用的.

    否则该对象x可以调用iff x->ob_type->tp_call != NULL

中应将描述tp_call字段:

ternaryfunc tp_call指向实现调用对象的函数的可选指针.如果对象不可调用,则此值应为NULL.签名与PyObject_Call()相同.该字段由子类型继承.

您始终可以使用内置callable函数来确定给定对象是否可调用; 或者更好,但只是打电话给它,然后赶上TypeError.callable在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')


@JF塞巴斯蒂安:这是BS,更像生活的例子更好.我可以向你展示生活般的代码,让你哭泣作为一个例子.简单的例子也可以工作,它们可以更好地说明一些东西,因为它们不会分散注意力.
我发现__call__方法的示例极具误导性,因为它将它与缓存和装饰器的配方混合在一起,这对于__call__的理解没有任何帮助.
您正在解释什么是可调用的,但您举例说明了如何使用可调用对象来定义装饰器.我知道这是__callable__的典型用法,但这可能会让想知道什么是可调用的读者以及如何使用__callable__的读者感到困惑.我更喜欢@FlorianBösch的回答.
JF塞巴斯蒂安,也写了更多你从其他地方复制和粘贴的例子并没有帮助.
@Kay:我也喜欢@FlorianBösch的答案(目前的形式).顺便说一句,装饰者不是*"可调用"的典型用法.最典型的"callables"是函数/方法,例如`def f():...`,以及类对象,例如`class C:...`ie,`f`,`''..strip`,` len`和`C`都是可调用的.在类中具有`__call __()`方法的实例相对较少.

3> Andrea Ambu..:

可调用对象允许您使用圆括号()并最终传递一些参数,就像函数一样.

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

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

func = a()

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

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



4> hcalves..:

让我向后解释:

考虑一下......

foo()

...作为语法糖:

foo.__call__()

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

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

int('10')
unicode(10)

你基本上是这样做的:

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

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



5> ConcernedOfT..:

Callable是具有该__call__方法的对象.这意味着你可以伪造可调用的函数或做一些像Partial Function Application这样的整洁的东西,你可以在这里使用函数并添加一些增强它或填充一些参数的东西,返回可以依次调用的东西(在函数式编程圈子中称为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 "", line 1, in 
TypeError: 'str' object is not callable
>>> 



6> Joe Skora..:

很简单,"可调用"是可以像方法一样调用的东西.内置函数"callable()"将告诉您某些内容是否可以调用,以及检查调用属性.函数可以像类一样调用,类实例可以调用.在这里和这里了解更多相关信息.



7> MvdD..:

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



8> Armin Ronach..:

在Python中,callable是一个类型有一个__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

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有