Josue Kouka

Josue Kouka

Code, Linux, and open source — one post at a time.

17 Jan 2015

Attacher une methode a une classe en python

Note (2026): Written for Python 2 (print, type(x) returning instancemethod) - the types.MethodType mechanism itself still works in Python 3, but the REPL output shown below won’t match exactly.

Serieusement, je ne vois pas trop dans quelle condition ceci peut etre utile, disons que c’est juste bon a savoir.

Soit un object Person

>>> class Person(object):
...   def __init__(self, name, age=None):
...     self.name = name
...     self.age = age
...   def introduce(self,):
...     print("Hi! My name is {0}".format(name))
...
>>> p = Person('josh', 25)
>>> p.introduce()
Hi ! My name is Josh

Disons que l’on veut ajouter une methode permettant de dire son age

>>> def iam(self,):
...   print("I'm {0}".format(self.age))
...
>>> p.iam = iam
>>> p.iam()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iam() takes exactly 1 argument (0 given)

Le code ci dessus ne marche pas, assez evident.

Parcontre si on passe bien notre instance a la methode celle ci s’execute normalement. Encore evident, vu que self designe l’instance a laquelle appartient la methode.

>>> p.iam(p)
I'm 25
>>>

Tout ceci a un sens en faisant ceci.

>>> type(p.introduce)
<type 'instancemethod'>
>>> type(p.iam)
<type 'function'>
>>>

On voit clairement que introduce est une methode d’instance, ce qui n’est pas le cas de iam (Je ne parle pas du groupe de musique lol).

On a toujours pas repondu a notre seule question : Comment ajouter une methode a une classe ou une instance de classe

Le mecanisme permettant de binder une methode a une classe ou une de ses instances

>>> from types import MethodType
>>> p.iam = MethodType(iam, p, Person)
>>> p.iam()
I'm 25
>>> 
>>> type(p.iam)
<type 'instancemethod'>
>>>

On voit bien que notre iam est bien une Methode d’instance et qu’on peut y faire un appel sans passer l’instance comme argument.

>>> pf = Person('Sarah', '24')
>>> pf.iam()
>>> Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'iam'
>>> Person.iam = MethodType(iam, None, Person)
>>> pf = Person('Sarah', 24)
>>> pf.iam()
I'm 24
>>>

Dans le code ci dessus, on voit bien que pour l’appliquer a toutes les nouvelles instances il faut ajouter la nouvelle methode a la classe.

Ben voila, pas sure que ce soit utile, mais plutot interressant a savoir.