O que é um "callable"?

310

Agora que está claro o que é uma metaclasse , existe um conceito associado que eu uso o tempo todo sem saber o que realmente significa.

Suponho que todo mundo tenha cometido um erro entre parênteses, resultando em uma exceção "o objeto não pode ser chamado". Além do mais, usar __init__e __new__levar a se perguntar para que __call__serve essa droga .

Você poderia me dar algumas explicações, incluindo exemplos com o método mágico?

e-satis
fonte
10
related: Python internals: how callables work
jfs 23/03

Respostas:

308

Um indicativo é qualquer coisa que possa ser chamada.

A built-in que pode ser chamado (PyCallable_Check em objects.c) verifica se o argumento é:

  • uma instância de uma classe com um __call__método ou
  • é de um tipo que possui um membro tp_call (c struct) não nulo que indica capacidade de chamada de outra forma (como em funções, métodos etc.)

O método nomeado __call__é (de acordo com a documentação )

Chamado quando a instância é '' chamada '' como uma função

Exemplo

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

foo_instance = Foo()
foo_instance() #this is calling the __call__ method
Florian Bösch
fonte
6
Note-se que o que pode ser chamado builtin está sendo removido em Python 3.0 em favor da verificação de chamada
Eli Courtwright
13
@Eli: Hmm isso soa como uma muito má jogada. callablena verdade diz se algo pode ser chamado ou não, enquanto a verificação não __call__diz nada; Se um objeto ofornecer __getattribute__ou __getattr__, hasattr(o, '__call__')pode retornar True, ainda oassim não será possível chamar porque o Python ignora __getattribute__e faz __getattr__chamadas. A única maneira real de verificar se algo pode ser chamado é, portanto, o EAFP.
#
49
@ Longpoke: Apenas para o registro, consulte a documentação do callable()Python 3.x : " Esta função foi removida primeiro no Python 3.0 e depois trazida de volta no Python 3.2. ".
Tadeck
Parece que no python 3.8 apenas a presença de tp_callé verificada. Veja a implementação do PyCallable_Check , são 3 linhas.
Michele Piccolini
84

Nas fontes do 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;
    }
}

Diz:

  1. Se um objeto é uma instância de alguma classe, é possível chamar se tiver __call__atributo.
  2. xCaso contrário, o objeto pode ser chamado se x->ob_type->tp_call != NULL

Descrição do tp_callcampo :

ternaryfunc tp_callUm ponteiro opcional para uma função que implementa a chamada do objeto. Isso deve ser NULL se o objeto não puder ser chamado. A assinatura é a mesma que para PyObject_Call (). Este campo é herdado por subtipos.

Você sempre pode usar a callablefunção interna para determinar se um determinado objeto é chamador ou não; ou melhor ainda, basta ligar e pegar TypeErrormais tarde. callableé removido no Python 3.0 e 3.1, use callable = lambda o: hasattr(o, '__call__')ou isinstance(o, collections.Callable).

Exemplo, uma implementação simplista de cache:

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    

Uso:

@Cached
def ack(x, y):
    return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1) 

Exemplo de biblioteca padrão, arquivo site.py, definição de embutidos exit()e quit()funções:

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')
jfs
fonte
10
Acho que o exemplo para o chamado método altamente missleading porque ele mistura-o com uma receita para cache e decoradores, que não acrescentam nada à compreensão da chamada
Florian Bösch
3
JF Sebastian, também empilhar mais exemplos que você copia e cola de outro lugar que não é mínimo não ajuda.
Florian Bösch
20
@JF Sebastian: É BS que exemplos mais realistas são melhores. Eu poderia lhe mostrar um código realista que faria você chorar como exemplo. Exemplos simples também funcionam e funcionam melhor para ilustrar algo porque não distraem.
Florian Bösch
5
Você está explicando o que é um callable, mas deu um exemplo de como usar objetos callable para definir um decorador. Eu sei que é um uso típico do que pode ser chamado , mas isso pode confundir os leitores que querem apenas saber o que é que pode ser chamado e como usar exigível . Prefiro a resposta de @Florian Bösch.
KFL 06/03
2
@Kay: Eu também gosto da resposta de @Florian Bösch (em sua forma atual). btw, um decorador não é um uso típico de um "callable". Maioria "chamáveis" típicas são funções / métodos, tais como def f(): ..., e classe de objectos, tais como class C: ...por exemplo, f, ''.strip, len, e Ctodas podem ser chamados. Instâncias que possuem um __call__()método em sua classe são relativamente raras.
JFS
37

Um callable é um objeto que permite usar parênteses arredondados () e, eventualmente, passar alguns parâmetros, assim como funções.

Toda vez que você define uma função, o python cria um objeto que pode ser chamado. Por exemplo, você pode definir a função func das seguintes maneiras (é a mesma):

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

func = a()

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

Você poderia usar esse método em vez de métodos como doit ou run , acho que é mais claro ver obj () do que obj.doit ()

Andrea Ambu
fonte
37

Deixe-me explicar ao contrário:

Considere isto...

foo()

... como açúcar sintático para:

foo.__call__()

Onde foopode ser qualquer objeto que responda __call__. Quando digo qualquer objeto, falo sério: tipos internos, suas próprias classes e suas instâncias.

No caso de tipos internos, quando você escreve:

int('10')
unicode(10)

Você está essencialmente fazendo:

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

É também por isso que você não possui foo = new intno Python: basta fazer com que o objeto de classe retorne uma instância dele __call__. A maneira como o Python resolve isso é muito elegante na minha opinião.

hcalves
fonte
Você está essencialmente fazendo type(int).__call__(int, '10')e type(unicode).__call__(unicode, '10'). Dunders são sempre chamados em sua classe, não através da instância. E eles nunca passam pela metaclasse também. Na maioria dos casos, isso é apenas um detalhe, mas às vezes importa.
Mad Physicist
11

Um Callable é um objeto que possui o __call__método Isso significa que você pode falsificar funções que podem ser chamadas ou fazer coisas legais, como Partial Function Application, onde você pega uma função e adiciona algo que a aprimora ou preenche alguns dos parâmetros, retornando algo que pode ser chamado por vez (conhecido como Currying nos círculos de programação funcional) )

Certos erros tipográficos farão com que o intérprete tente chamar algo que você não pretendia, como (por exemplo) uma string. Isso pode gerar erros quando o intérprete tenta executar um aplicativo não solicitável. Você pode ver isso acontecendo em um intérprete python, fazendo algo como a transcrição abaixo.

[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
>>> 
ConcernedOfTunbridgeWells
fonte
9

__call__ torna qualquer objeto que pode ser chamado como uma função.

Este exemplo produzirá 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)
MvdD
fonte
7

Muito simplesmente, um "chamado" é algo que pode ser chamado como um método. A função interna "callable ()" informará se algo parece ser solicitável, assim como a verificação de uma propriedade de chamada . É possível chamar funções, assim como classes, instâncias de classe. Veja mais sobre isso aqui e aqui .

Joe Skora
fonte
5

No Python, uma chamada é um objeto cujo tipo possui um __call__método:

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

Tão simples como isso :)

Obviamente, isso pode ser sobrecarregado:

>>> class Foo(object):
...  def __call__(self):
...   return 42
... 
>>> f = Foo()
>>> f()
42
Armin Ronacher
fonte
3

Verificar a função ou o método da classe é exigível ou não, o que significa que podemos chamar essa função.

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
Ravi Singh
fonte
1
Tem certeza de callable(obj.__init___)que não possui um sublinhado extra (como em AttributeError)? Caso contrário, você tem certeza de que a resposta não é Trueessa?
Mad Physicist
2

É algo que você pode colocar "(args)" depois e esperar que funcione. Uma chamada é geralmente um método ou uma classe. Os métodos são chamados, as classes são instanciadas.

Kevin Conner
fonte
2

callables implementam o __call__método especial para que qualquer objeto com esse método possa ser chamado.

cobie
fonte
Uma instância na qual você define __call__não poderá ser chamada se a classe não definir esse método.
Mad Physicist
2

Callable é um tipo ou classe de "Função ou Método Integrado" com uma chamada de método

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

Exemplo: print é um objeto que pode ser chamado. Com uma função interna __call__ Quando você invoca a função print , o Python cria um objeto do tipo print e invoca seu método __call__ passando os parâmetros, se houver.

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

Obrigado. Atenciosamente, Maris

maris
fonte
1
Algumas das informações aqui estão erradas. Por exemplo, "quando você invoca a printfunção, o Python cria um objeto do tipo print e invoca seu método __call__". Python não cria um objeto de impressão. Apenas chama algo equivalente a type(print).__call__(print, *args, **kwargs). E a primeira frase não faz muito sentido. Você parece estar confundindo um objeto que pode ser chamado e "chamado" da função.
Mad Physicist