web-dev-qa-db-fra.com

Les fonctions sont-elles des objets en Python?

J'entends toujours cette déclaration en Python (pour des sujets tels que les décorateurs, etc. lorsque vous passez des fonctions, etc.) mais je n'ai jamais vraiment vu d'élaboration à ce sujet.

Par exemple, est-il possible de créer une classe c qui n'a qu'une seule méthode abstraite qui est appelée avec un ensemble de crochets ouverts et fermés.

i.e class c:
       @abstractmethod
       def method_to_be_called_by():
        ... 

pour que vous puissiez avoir

c(whatever parameters are required)

Je pourrais être loin du compte avec ma compréhension ici, j'étais simplement curieux de savoir ce que les gens voulaient dire par là.

21
user3684792

Vous recherchez la méthode __call__ . Les objets fonction ont cette méthode:

>>> def foo(): pass
... 
>>> foo.__call__
<method-wrapper '__call__' of function object at 0x106aafd70>

Ce n'est pas que la boucle d'interprétation Python utilise effectivement cette méthode lors de la rencontre d'un objet fonction Python; les optimisations de l'implémentation sautent directement au bytecode contenu dans la plupart des cas) .

Mais vous pouvez utilisez cela sur votre propre classe personnalisée:

class Callable(object):
    def __init__(self, name):
        self.name = name

    def __call__(self, greeting):
        return '{}, {}!'.format(greeting, self.name)

Démo:

>>> class Callable(object):
...     def __init__(self, name):
...         self.name = name
...     def __call__(self, greeting):
...         return '{}, {}!'.format(greeting, self.name)
... 
>>> Callable('World')('Hello')
'Hello, World!'

Python crée des objets fonction pour vous lorsque vous utilisez une instruction def , ou vous utilisez une expression lambda :

>>> def foo(): pass
... 
>>> foo
<function foo at 0x106aafd70>
>>> lambda: None
<function <lambda> at 0x106d90668>

Vous pouvez comparer cela à la création d'une chaîne ou d'un entier ou d'une liste à l'aide de la syntaxe littérale:

listobject = [1, 'two']

Ce qui précède crée 3 objets sans jamais appeler de type, Python a fait tout cela pour vous en fonction de la syntaxe utilisée. La même chose s'applique aux fonctions.

En créer un vous-même peut être un peu plus complexe; vous devez avoir un objet de code et une référence à un espace de noms global, au minimum:

>>> function_type = type(lambda: None)
>>> function_type
<type 'function'>
>>> function_type(foo.__code__, globals(), 'bar')
<function bar at 0x106d906e0>

Ici, j'ai créé un objet fonction en réutilisant le type function, en prenant l'objet code de la fonction foo; le type de fonction n'est pas un nom intégré mais le type existe vraiment et peut être obtenu en appelant type() sur une instance de fonction existante.

J'ai également passé dans l'espace de noms global de mon interprète, et un nom; ce dernier est un argument facultatif; sinon, le nom est extrait de l'objet code.

30
Martijn Pieters

Une façon simple de voir cela est de créer une fonction dans l'interpréteur Python def bar(x): return x + 1 puis d'utiliser dir(bar) pour voir les différents attributs magiques, y compris __class__.

Oui, python sont des objets complets.

Pour une autre approche, les objets sont des fonctions s'ils ont une méthode magic __call__() .

5
shapr