问题:什么是“可赎回”?

既然清楚了什么是元类,就有一个相关的概念,我一直都在使用它,而不知道它的真正含义。

我想每个人都曾因括号错误而导致“对象不可调用”异常。而且,使用__init____new__导致怀疑这种血腥的__call__用途。

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

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 a mistake with parenthesis, resulting in an “object is not callable” exception. What’s more, using __init__ and __new__ lead to wonder what this bloody __call__ can be used for.

Could you give me some explanations, including examples with the magic method ?


回答 0

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

所述内置的可调用(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

A callable is anything that can be called.

The built-in callable (PyCallable_Check in objects.c) checks if the argument is either:

  • an instance of a class with a __call__ method or
  • is of a type that has a non null tp_call (c struct) member which indicates callability otherwise (such as in functions, methods etc.)

The method named __call__ is (according to the documentation)

Called when the instance is ”called” as a function

Example

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

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

回答 1

从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函数来确定给定对象是否可调用;或更好,只是调用它并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) 

来自标准库,文件,内置定义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')

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 , 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')

回答 2

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

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

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

func = a()

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

您可以使用此方法代替doitrun之类的方法,我认为看到obj()比obj.doit()更清楚

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


回答 3

让我向后解释:

考虑一下…

foo()

…作为以下方面的语法糖:

foo.__call__()

foo响应的对象在哪里__call__?当我说任何对象时,我的意思是:内置类型,您自己的类及其实例。

对于内置类型,在编写时:

int('10')
unicode(10)

您实际上是在做:

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

这就是为什么您没有使用foo = new intPython:只需使class对象在上返回它的一个实例__call__。我认为Python解决此问题的方式非常优雅。

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.


回答 4

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 "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> 

A Callable is an object that has the __call__ method. This means you can fake callable functions or do neat things like Partial Function Application where you take a function and add something that enhances it or fills in some of the parameters, returning something that can be called in turn (known as Currying in functional programming circles).

Certain typographic errors will have the interpreter attempting to call something you did not intend, such as (for example) a string. This can produce errors where the interpreter attempts to execute a non-callable application. You can see this happening in a python interpreter by doing something like the transcript below.

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

回答 5

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

__call__ makes any object be callable as a function.

This example will output 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)

回答 6

很简单,“可调用”是可以像方法一样被调用的东西。内置函数“ callable()”将告诉您是否有某些东西可调用,就像检查call属性一样。函数可以像类一样被调用,类实例可以被调用。在这里这里看到更多关于这个的信息

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.


回答 7

在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

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

回答 8

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

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

To check function or method of class is callable or not that means we can call that function.

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

回答 9

您可以在其后加上“(args)”,并期望它能正常工作。可调用对象通常是方法或类。方法被调用,类被实例化。

It’s something you can put “(args)” after and expect it to work. A callable is usually a method or a class. Methods get called, classes get instantiated.


回答 10

可调用__call__对象实现特殊方法,因此具有这种方法的任何对象都是可调用的。

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


回答 11

可调用是带有方法调用的 “内置函数或方法”的类型或类

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

示例: print是一个可调用对象。使用内置函数__call__ 调用print函数时,Python创建类型为print对象,并调用其方法__call__并传递参数(如果有)。

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

谢谢。问候,马里斯

Callable is a type or class of “Build-in function or Method” with a method call

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

Example: print is a callable object. With a build-in function __call__ When you invoke the print function, Python creates an object of type print and invokes its method __call__ passing the parameters if any.

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

Thank you. Regards, Maris


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。