Qu'est-ce qu'un «appelable»?

312

Maintenant que c'est clair ce qu'est une métaclasse , il y a un concept associé que j'utilise tout le temps sans savoir ce que cela signifie vraiment.

Je suppose que tout le monde a fait une fois une erreur entre parenthèses, ce qui a entraîné une exception "l'objet n'est pas appelable". De plus, utiliser __init__et __new__amener à se demander à quoi __call__peut servir ce sanglant .

Pourriez-vous me donner quelques explications, y compris des exemples avec la méthode magique?

e-satis
la source

Réponses:

310

Un appelable est tout ce qui peut être appelé.

Le haut- appelable (PyCallable_Check en objects.C) vérifie si l'argument est soit:

  • une instance d'une classe avec une __call__méthode ou
  • est d'un type qui a un membre tp_call (c struct) non nul qui indique autrement l'appel (comme dans les fonctions, les méthodes, etc.)

La méthode nommée __call__est ( selon la documentation )

Appelé lorsque l'instance est '' appelée '' en tant que fonction

Exemple

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

foo_instance = Foo()
foo_instance() #this is calling the __call__ method
Florian Bösch
la source
6
Notez que l'appelable intégré est supprimé dans Python 3.0 au profit de la vérification de l' appel
Eli Courtwright
13
@Eli: Hmm ça sonne comme un très mauvais coup. callablevous indique réellement si quelque chose est appelable ou non, tandis que la vérification __call__ne vous dit rien; Si un objet ofournit __getattribute__ou __getattr__, hasattr(o, '__call__')peut retourner vrai, mais one sera pas encore appelable parce que Python ignore __getattribute__et __getattr__pour les appels. Le seul véritable moyen qui reste pour vérifier si quelque chose est appelable est donc EAFP.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
49
@Longpoke: Pour mémoire, veuillez consulter la documentation de callable()Python 3.x : " Cette fonction a d'abord été supprimée en Python 3.0 puis ramenée en Python 3.2. ".
Tadeck
Il semble qu'en python 3.8 seule la présence de tp_callest vérifiée. Voir l'implémentation de PyCallable_Check , c'est 3 lignes.
Michele Piccolini
84

Depuis les sources de 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;
    }
}

Ça dit:

  1. Si un objet est une instance d'une classe, il peut être appelé s'il n'a pas d' __call__attribut.
  2. Sinon, l'objet xpeut être appelé si x->ob_type->tp_call != NULL

Description du tp_callchamp :

ternaryfunc tp_callUn pointeur facultatif vers une fonction qui implémente l'appel de l'objet. Cela devrait être NULL si l'objet n'est pas appelable. La signature est la même que pour PyObject_Call (). Ce champ est hérité par des sous-types.

Vous pouvez toujours utiliser la callablefonction intégrée pour déterminer si un objet donné peut être appelé ou non; ou mieux encore appelez-le et attrapez TypeErrorplus tard. callableest supprimé dans Python 3.0 et 3.1, utilisez callable = lambda o: hasattr(o, '__call__')ou isinstance(o, collections.Callable).

Exemple, une implémentation de cache simpliste:

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) 

Exemple de bibliothèque standard, fichier site.py, définition de fonction intégrée exit()et quit()fonctions:

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
la source
10
Je trouve l'exemple de la méthode d' appel très trompeur car il le mélange avec une recette pour la mise en cache et les décorateurs, qui n'ajoutent rien à la compréhension de l' appel
Florian Bösch
3
JF Sebastian, empiler également plus d'exemples que vous copiez et collez ailleurs qui ne sont pas minimes n'aide pas.
Florian Bösch le
20
@JF Sebastian: C'est BS que des exemples plus réalistes sont meilleurs. Je pourrais vous montrer un code réaliste qui vous ferait pleurer comme exemple. Des exemples simples fonctionnent aussi, et ils fonctionnent mieux pour illustrer quelque chose parce qu'ils ne distraient pas.
Florian Bösch
5
Vous expliquez ce qu'est un appelable, mais vous avez donné un exemple sur la façon d'utiliser des objets appelables pour définir un décorateur. Je sais que c'est une utilisation typique de callable mais cela peut confondre les lecteurs qui veulent juste savoir ce qui est callable et comment utiliser callable . Je préfère la réponse de @Florian Bösch.
KFL
2
@Kay: J'aime aussi la réponse de @Florian Bösch (dans sa forme actuelle). btw, un décorateur n'est pas un usage typique d'un "callable". Le plus typique « appelables » sont des fonctions / méthodes telles que def f(): ...et des objets de classe tels que par class C: ...exemple, f, ''.strip, lenet Ctous sont appelable. Les instances qui ont une __call__()méthode dans leur classe sont relativement rares.
jfs
37

Un callable est un objet qui vous permet d'utiliser des parenthèses rondes () et éventuellement de passer certains paramètres, tout comme les fonctions.

Chaque fois que vous définissez une fonction, python crée un objet appelable. Par exemple, vous pouvez définir la fonction func de ces façons (c'est la même chose):

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

func = a()

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

Vous pouvez utiliser cette méthode au lieu de méthodes comme doit ou run , je pense qu'il est plus clair de voir obj () que obj.doit ()

Andrea Ambu
la source
37

Permettez-moi d'expliquer à l'envers:

Considère ceci...

foo()

... comme sucre syntaxique pour:

foo.__call__()

foopeut être n'importe quel objet qui répond __call__. Quand je dis n'importe quel objet, je le pense: les types intégrés, vos propres classes et leurs instances.

Dans le cas des types intégrés, lorsque vous écrivez:

int('10')
unicode(10)

Vous faites essentiellement:

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

C'est aussi pourquoi vous n'en avez pas foo = new inten Python: vous faites juste en sorte que l'objet classe en retourne une instance __call__. La façon dont Python résout cela est très élégante à mon avis.

hcalves
la source
Vous faites essentiellement type(int).__call__(int, '10')et type(unicode).__call__(unicode, '10'). Les dunders sont toujours appelés sur leur classe, pas via l'instance. Et ils ne passent jamais par la métaclasse non plus. Dans la plupart des cas, ce n'est qu'un coup de pouce, mais cela compte parfois.
Mad Physicist
11

Un Callable est un objet qui a la __call__méthode. Cela signifie que vous pouvez simuler des fonctions appelables ou faire des choses intéressantes comme l'application de fonction partielle où vous prenez une fonction et ajoutez quelque chose qui l'améliore ou remplit certains des paramètres, renvoyant quelque chose qui peut être appelé à son tour (connu sous le nom de Currying dans les cercles de programmation fonctionnelle ).

Certaines erreurs typographiques auront l'interpréteur tentant d'appeler quelque chose que vous ne vouliez pas, comme (par exemple) une chaîne. Cela peut produire des erreurs lorsque l'interpréteur tente d'exécuter une application non appelable. Vous pouvez voir cela se produire dans un interpréteur python en faisant quelque chose comme la transcription ci-dessous.

[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
la source
9

__call__ rend tout objet appelable en tant que fonction.

Cet exemple affichera 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
la source
7

Tout simplement, un "callable" est quelque chose qui peut être appelé comme une méthode. La fonction intégrée "callable ()" vous dira si quelque chose semble être appelable, tout comme la vérification d'une propriété d' appel . Les fonctions sont appelables tout comme les classes, les instances de classe peuvent être appelables. En savoir plus ici et ici .

Joe Skora
la source
5

En Python, un appelable est un objet dont le type a une __call__méthode:

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

Aussi simple que cela :)

Bien sûr, cela peut être surchargé:

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

Pour vérifier que la fonction ou la méthode de la classe est appelable ou non, cela signifie que nous pouvons appeler cette fonction.

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
la source
1
Êtes-vous sûr de callable(obj.__init___)ne pas avoir de soulignement supplémentaire (comme dans AttributeError)? Si ce n'est pas le cas, êtes-vous sûr que la réponse n'est pas Truepour celle-là?
Mad Physicist
2

C'est quelque chose que vous pouvez mettre "(args)" après et vous attendre à ce que cela fonctionne. Un appelable est généralement une méthode ou une classe. Les méthodes sont appelées, les classes sont instanciées.

Kevin Conner
la source
2

callables implémentent la __call__méthode spéciale de sorte que tout objet avec une telle méthode est appelable.

cobie
la source
Une instance sur laquelle vous définissez __call__ne sera pas appelable si la classe ne définit pas une telle méthode.
Mad Physicist
2

Callable est un type ou une classe de "fonction ou méthode intégrée" avec un appel de méthode

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

Exemple: print est un objet appelable. Avec une fonction intégrée __call__ Lorsque vous appelez la fonction print , Python crée un objet de type print et invoque sa méthode __call__ en passant les paramètres éventuels.

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

Je vous remercie. Cordialement, Maris

maris
la source
1
Certaines informations ici sont tout à fait erronées. Par exemple "Lorsque vous appelez la printfonction, Python crée un objet de type print et invoque sa méthode __call__". Python ne crée pas d'objet d'impression. Cela appelle simplement quelque chose d'équivalent type(print).__call__(print, *args, **kwargs). Et la première phrase n'a pas beaucoup de sens. Vous semblez confondre un objet appelable et "appelable" la fonction.
Mad Physicist