Che cos'è un "richiamo"?


311

Ora che è chiaro cosa sia una metaclasse , esiste un concetto associato che uso sempre senza sapere cosa significhi davvero.

Suppongo che una volta tutti abbiano commesso un errore con la parentesi, risultando in un'eccezione "oggetto non chiamabile". Inoltre, usare __init__e __new__portare a chiedersi a cosa __call__possa essere usato questo maledetto .

Potresti darmi qualche spiegazione, inclusi esempi con il metodo magico?


Risposte:


309

Un callable è tutto ciò che può essere chiamato.

Il built-in callable (PyCallable_Check in objects.c) controlla se l'argomento è uno:

  • un'istanza di una classe con un __call__metodo o
  • è di un tipo che ha un membro tp_call (c struct) non nullo che indica diversamente la callability (come in funzioni, metodi ecc.)

Il metodo denominato __call__è ( secondo la documentazione )

Chiamato quando l'istanza è "chiamata" come funzione

Esempio

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

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

6
Si noti che il richiamo
Eli Courtwright,

13
@Eli: Hmm che suona come una mossa molto brutta. callablein realtà ti dice se qualcosa è richiamabile o meno, mentre il controllo per __call__non ti dice nulla; Se un oggetto ofornisce __getattribute__o __getattr__, hasattr(o, '__call__')può restituire True, tuttavia non osarà ancora richiamabile perché Python salta __getattribute__e __getattr__per le chiamate. L'unico vero modo rimasto per verificare se qualcosa è richiamabile è quindi EAFP.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

49
@Longpoke: Solo per la cronaca, consultare la documentazione callable()in Python 3.x : " Questa funzione è stata rimossa dapprima in Python 3.0 e poi riportata in Python 3.2. ".
Tadeck,

Sembra che in Python 3.8 tp_callsia verificata solo la presenza di . Vedi l'implementazione di PyCallable_Check , sono 3 righe.
Michele Piccolini,

84

Dalle fonti di 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;
    }
}

Dice:

  1. Se un oggetto è un'istanza di qualche classe, è richiamabile se ha un __call__attributo.
  2. Altrimenti l'oggetto xè richiamabile iff x->ob_type->tp_call != NULL

Descrizione del tp_callcampo :

ternaryfunc tp_callUn puntatore facoltativo a una funzione che implementa la chiamata dell'oggetto. Dovrebbe essere NULL se l'oggetto non è richiamabile. La firma è la stessa di PyObject_Call (). Questo campo è ereditato dai sottotipi.

È sempre possibile utilizzare la callablefunzione integrata per determinare se un determinato oggetto è richiamabile o meno; o meglio, basta chiamarlo e catturare TypeErrorpiù tardi. callableviene rimosso in Python 3.0 e 3.1, utilizzare callable = lambda o: hasattr(o, '__call__')o isinstance(o, collections.Callable).

Esempio, un'implementazione della cache semplicistica:

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) 

Esempio da libreria standard, file site.py, definizione di built-in exit()e quit()funzioni:

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

10
Trovo l'esempio per la chiamata di metodo altamente missleading perché mescola con una ricetta per il caching e decoratori, che aggiungono nulla alla comprensione della chiamata
Florian Bösch

3
JF Sebastian, anche accumulare più esempi che hai copiato e incollato da qualche altra parte che non sono minimi non aiuta.
Florian Bösch,

20
@JF Sebastian: È BS che gli esempi più realistici sono migliori. Potrei mostrarti un codice realistico che ti farebbe piangere come esempio. Anche esempi semplici funzionano e funzionano meglio per illustrare qualcosa perché non distraggono.
Florian Bösch,

5
Stai spiegando cos'è un callable, ma hai dato un esempio su come usare oggetti richiamabili per definire un decoratore. So che è un uso tipico di callable ma questo può confondere i lettori che vogliono solo sapere cosa è callable e come usare callable . Preferirei la risposta di @Florian Bösch.
KFL

2
@Kay: Mi piace anche la risposta di @Florian Bösch (nella sua forma attuale). tra l'altro, un decoratore non è un tipico utilizzo di un "callable". Più "chiamabili" tipici sono funzioni / metodi come def f(): ..., e oggetti di classe come class C: ...esempio, f, ''.strip, len, e Ctutti sono richiamabili. Le istanze che hanno un __call__()metodo nella loro classe sono relativamente rare.
jfs

37

Un callable è un oggetto che consente di utilizzare la parentesi tonda () e infine passare alcuni parametri, proprio come le funzioni.

Ogni volta che si definisce una funzione python crea un oggetto richiamabile. Ad esempio, è possibile definire la funzione func in questi modi (è la stessa):

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

func = a()

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

Potresti usare questo metodo invece di metodi come doit o run , penso che sia solo più chiaro vedere obj () che obj.doit ()


37

Lasciami spiegare al contrario:

Considera questo ...

foo()

... come zucchero sintattico per:

foo.__call__()

Dove foopuò essere qualsiasi oggetto che risponde __call__. Quando dico qualsiasi oggetto, intendo: tipi incorporati, le tue classi e le loro istanze.

Nel caso di tipi predefiniti, quando scrivi:

int('10')
unicode(10)

Stai essenzialmente facendo:

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

Questo è anche il motivo per cui non hai foo = new intin Python: fai semplicemente restituire all'oggetto classe un'istanza __call__. Il modo in cui Python risolve questo è molto elegante secondo me.


Stai essenzialmente facendo type(int).__call__(int, '10')e type(unicode).__call__(unicode, '10'). I dunder sono sempre chiamati nella loro classe, non attraverso l'istanza. E non passano mai neanche attraverso la metaclasse. Per la maggior parte dei casi è solo un gioco da ragazzi, ma a volte importa.
Fisico pazzo,

11

Un callable è un oggetto che ha il __call__metodo. Ciò significa che puoi falsificare funzioni richiamabili o fare cose ordinate come l' applicazione di funzioni parziali in cui prendi una funzione e aggiungi qualcosa che la migliora o riempie alcuni parametri, restituendo qualcosa che può essere chiamato a sua volta (noto come Currying nei circoli di programmazione funzionale ).

Alcuni errori tipografici avranno l'interprete che tenta di chiamare qualcosa che non intendevi, come (ad esempio) una stringa. Ciò può produrre errori nei casi in cui l'interprete tenta di eseguire un'applicazione non richiamabile. Puoi vederlo accadere in un interprete Python facendo qualcosa di simile alla trascrizione di seguito.

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

9

__call__ rende qualsiasi oggetto richiamabile come funzione.

Questo esempio produrrà 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)

7

Molto semplicemente, un "richiamo" è qualcosa che può essere chiamato come un metodo. La funzione integrata "callable ()" ti dirà se qualcosa sembra essere richiamabile, così come il controllo di una proprietà call . Le funzioni sono richiamabili come le classi, le istanze di classe possono essere richiamabili. Vedi di più qui e qui .


5

In Python un callable è un oggetto il cui tipo ha un __call__metodo:

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

Così semplice :)

Questo ovviamente può essere sovraccarico:

>>> class Foo(object):
...  def __call__(self):
...   return 42
... 
>>> f = Foo()
>>> f()
42

3

Controllare che la funzione o il metodo della classe sia richiamabile o meno significa che possiamo chiamare quella funzione.

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

1
Sei sicuro di callable(obj.__init___)non avere un carattere di sottolineatura aggiuntivo (come in AttributeError)? In caso contrario, sei sicuro che la risposta non sia Trueper quella?
Fisico pazzo,

2

È qualcosa che puoi mettere dopo "(args)" e aspettarti che funzioni. Un callable è di solito un metodo o una classe. I metodi vengono chiamati, le classi vengono istanziate.


2

i callable implementano il __call__metodo speciale in modo che qualsiasi oggetto con tale metodo sia richiamabile.


Un'istanza su cui si definisce __call__non sarà richiamabile se la classe non definisce tale metodo.
Fisico pazzo,

2

Callable è un tipo o una classe di "Funzione o metodo integrato" con una chiamata al metodo

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

Esempio: print è un oggetto richiamabile. Con una funzione integrata __call__ Quando si richiama la funzione di stampa , Python crea un oggetto di tipo print e invoca il suo metodo __call__ passando eventuali parametri.

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

Grazie. Saluti, Maris


1
Alcune delle informazioni qui sono sbagliate. Ad esempio "Quando invochi la printfunzione, Python crea un oggetto di tipo print e invoca il suo metodo __call__". Python non crea un oggetto di stampa. Si chiama semplicemente qualcosa di equivalente a type(print).__call__(print, *args, **kwargs). E la prima frase non ha molto senso. Sembra che tu stia confondendo un oggetto richiamabile e "richiamabile" la funzione.
Fisico pazzo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.