web-dev-qa-db-fra.com

Avantages de l'utilisation de MethodType dans Python

Quels sont les avantages d'utiliser MethodType à partir du module types? Vous pouvez l'utiliser pour ajouter des méthodes à un objet. Mais nous pouvons le faire facilement sans:

def func():
   print 1

class A:
   pass

obj = A()
obj.func = func

Cela fonctionne même si nous supprimons func dans la portée principale en exécutant del func.

Pourquoi voudrait-on utiliser MethodType? Est-ce juste une convention ou une bonne habitude de programmation?

20
Existent

En fait, la différence entre l'ajout dynamique de méthodes au moment de l'exécution et votre exemple est énorme:

  • dans votre cas, vous attachez simplement une fonction à un objet, vous pouvez l'appeler bien sûr mais elle est non liée, elle n'a aucune relation avec l'objet lui-même (c'est-à-dire que vous ne pouvez pas utiliser self à l'intérieur de la fonction)
  • lorsqu'il est ajouté avec MethodType, vous créez une méthode bound et il se comporte comme une méthode normale Python pour l'objet, vous devez prendre l'objet auquel il appartient comme premier argument (il est normalement appelé self) et vous pouvez y accéder à l'intérieur de la fonction

Cet exemple montre la différence:

def func(obj):
  print 'I am called from', obj
class A:
  pass
a=A()
a.func=func
a.func()

Cela échoue avec une TypeError: func() takes exactly 1 argument (0 given), alors que ce code fonctionne comme prévu:

import types
a.func = types.MethodType(func, a) # or types.MethodType(func, a, A) for PY2
a.func()

affiche I am called from <__main__.A instance at xxx>.

19
mguijarr

Une utilisation courante de types.MethodType Consiste à vérifier si un objet est une méthode. Par exemple:

>>> import types
>>> class A(object):
...     def method(self):
...         pass
...
>>> isinstance(A().method, types.MethodType)
True
>>> def nonmethod():
...     pass
...
>>> isinstance(nonmethod, types.MethodType)
False

Notez que dans votre exemple, isinstance(obj.func, types.MethodType) renvoie False. Imaginez que vous avez défini une méthode meth dans la classe A. isinstance(obj.meth, types.MethodType) retournerait True.

4
Manuel Jacob