Plus sérieusement, le "instance comme argument", à l'utilisation, ça permet de rester cohérent sans introduire de syntaxe magique. Par exemple, supposons que a soit une instance de la classe A, qui hérite de la classe B, qui définissent tous deux une méthode foo. En C++, pour appeler le foo de B, tu aurais une syntaxe magique (de mémoire, ça fait un moment que j'ai plus fais de C++) et absolument immonde du type: a::B.foo(). En python, tu restes cohérent: B.foo est une fonction, tu as juste à l'appeler comme n'importe quelle fonction: B.foo(a).
Autre avantage, si tu prends x = [a1,a2,a3] (trois instances de A) et que tu veux appeler foo sur ces trois, tu as juste à faire map(A.foo, x): cela va donner [A.foo(a1), A.foo(a2), A.foo(a3)], ce qui, grace à l'argument explicite, est équivalent à [a1.foo(), a2.foo(), a3.foo()]
Autre avantage (le principal IMHO), l'instance passe très bien à travers les arguments du type *args ou **kwargs (l'équivalent, en plus puissant, des ... du C, comme avec printf). Ou à travers des décorateurs.
Enfin, ce n'est pas parce qu'une fonction est dans une classe que c'est une méthode d'instance (méthode de classe/statique). Là où un autre langage demanderait probablement "yet another keyword", en python, ça se fait par un décorateur tellement basique que n'importe quel pékin peut écrire soit même si ça le chante (il y en a un "standard", mais pour t'illustrer à quel point ça évite les cas et les constructions particuliers, je vais le faire moi-meme):
>>> def classmethod(meth):
... def call(*args, **kwargs):
... return meth(args[0].__class__, *args[1:], **kwargs)
... return call
...
>>> class Spam:
... @classmethod
... def hello(klass, who):
... print "Hello, %s (from %r)" % (who, klass)
...
>>> s = Spam()
>>> s.hello("world")
Hello, world (from <class __main__.Spam at 0xb7c6b7dc>)
[^] # Re: troll de noel
Posté par Moonz . En réponse à la dépêche Ruby 1.9.0 est sorti pour Noël. Évalué à 2.
>>>class Spam:
...a = 5
...
>>>def egg(self):
...print self.a
...
>>>x = Spam()
>>>Spam.egg = egg
>>>x.egg()
5
>>>egg(x)
5
Plus sérieusement, le "instance comme argument", à l'utilisation, ça permet de rester cohérent sans introduire de syntaxe magique. Par exemple, supposons que a soit une instance de la classe A, qui hérite de la classe B, qui définissent tous deux une méthode foo. En C++, pour appeler le foo de B, tu aurais une syntaxe magique (de mémoire, ça fait un moment que j'ai plus fais de C++) et absolument immonde du type: a::B.foo(). En python, tu restes cohérent: B.foo est une fonction, tu as juste à l'appeler comme n'importe quelle fonction: B.foo(a).
Autre avantage, si tu prends x = [a1,a2,a3] (trois instances de A) et que tu veux appeler foo sur ces trois, tu as juste à faire map(A.foo, x): cela va donner [A.foo(a1), A.foo(a2), A.foo(a3)], ce qui, grace à l'argument explicite, est équivalent à [a1.foo(), a2.foo(), a3.foo()]
Autre avantage (le principal IMHO), l'instance passe très bien à travers les arguments du type *args ou **kwargs (l'équivalent, en plus puissant, des ... du C, comme avec printf). Ou à travers des décorateurs.
Enfin, ce n'est pas parce qu'une fonction est dans une classe que c'est une méthode d'instance (méthode de classe/statique). Là où un autre langage demanderait probablement "yet another keyword", en python, ça se fait par un décorateur tellement basique que n'importe quel pékin peut écrire soit même si ça le chante (il y en a un "standard", mais pour t'illustrer à quel point ça évite les cas et les constructions particuliers, je vais le faire moi-meme):
>>> def classmethod(meth):
... def call(*args, **kwargs):
... return meth(args[0].__class__, *args[1:], **kwargs)
... return call
...
>>> class Spam:
... @classmethod
... def hello(klass, who):
... print "Hello, %s (from %r)" % (who, klass)
...
>>> s = Spam()
>>> s.hello("world")
Hello, world (from <class __main__.Spam at 0xb7c6b7dc>)