Что такое "вызываемый" в Python?

Теперь, когда ясно, что такое метакласс, есть связанная концепция, которую я использую все время, не зная, что это на самом деле означает.

Я полагаю, что все однажды допустили ошибку с круглыми скобками, что привело к исключению "объект не может быть вызван". Более того, используя __init__ а также __new__ привести к удивлению, что это кровавое __call__ может быть использован для.

Не могли бы вы дать мне некоторые объяснения, в том числе примеры с магическим методом?

13 ответов

Решение

Вызываемым является все, что можно назвать.

Встроенный callable (PyCallable_Check в objects.c) проверяет, является ли аргумент одним из следующих:

  • экземпляр класса с методом __call__ или
  • имеет тип, который имеет ненулевой член tp_call (c struct), который указывает на возможность вызова в противном случае (например, в функциях, методах и т. д.)

Метод с именем __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 вызывается,если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')

Вызываемый объект - это объект, который позволяет вам использовать круглые скобки () и в итоге передавать некоторые параметры, как функции.

Каждый раз, когда вы определяете функцию, 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)

Вот почему у вас нет foo = new int в Python: вы просто заставляете объект класса возвращать его экземпляр на __call__, Способ, которым Python решает эту проблему, на мой взгляд, очень элегантен.

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

Callable - это объект, который имеет __call__ метод. Это означает, что вы можете подделывать вызываемые функции или делать изящные вещи, такие как Partial Function Application, где вы берете функцию и добавляете что-то, что улучшает ее или заполняет некоторые параметры, возвращая что-то, что может быть вызвано по очереди (это называется каррированием в кругах функционального программирования).).

В некоторых типографских ошибках интерпретатор пытается вызвать то, что вы не хотели, например, например, строку. Это может привести к ошибкам, когда интерпретатор пытается выполнить не вызываемое приложение. Вы можете увидеть это в интерпретаторе 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()" сообщит вам, кажется ли что-то вызываемым, как и проверка свойства вызова. Функции могут быть вызваны как классы, экземпляры классов могут быть вызваны. Подробнее об этом здесь и здесь.

В 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

Это то, что вы можете поставить "(аргументы)" после и ожидать, что это сработает. Вызываемый - это обычно метод или класс. Методы вызываются, классы создаются.

Callable - это тип или класс "встроенной функции или метода" свызовом метода.

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

Спасибо. С уважением, Марис

Вызовы реализуют __call__ специальный метод, поэтому любой объект с таким методом может быть вызван.

Класс, функция, метод и объект, который имеет callable .

Вы можете проверить, можно ли вызывать с помощью callable() , который возвращаетTrueесли вызывается и возвращает, если не вызывается, как показано ниже:

      class Class1:
    def __call__(self):
        print("__call__")

class Class2:
    pass

def func():
    pass

print(callable(Class1))   # Class1
print(callable(Class2))   # Class2

print(callable(Class1())) # Class1 object
print(callable(Class2())) # Class2 object

print(callable(func))     # func

Тогда только Class2объект , не имеющий__call__()не вызывается, как показано ниже:

      True  # Class1
True  # Class2
True  # Class1 object
False # Class2 object
True  # func

Кроме того, все нижеперечисленные функции нельзя вызывать, возвращаяFalseкак показано ниже:

      print(callable("Hello"))  # "str" type
print(callable(100))      # "int" type
print(callable(100.23))   # "float" type
print(callable(100 + 2j)) # "complex" type
print(callable(True))     # "bool" type
print(callable(None))     # "NoneType"
print(callable([]))       # "list" type
print(callable(()))       # "tuple" type
print(callable({}))       # "dict" type
print(callable({""}))     # "set" type

Выход:

      False # "str" type
False # "int" type
False # "float" type
False # "complex" type
False # "bool" type
False # "NoneType"
False # "list" type
False # "tuple" type
False # "dict" type
False # "set" type
Другие вопросы по тегам