• [^] # Re: troll de noel

    Posté par . En réponse à la dépêche Ruby 1.9.0 est sorti pour Noël. Évalué à 2.

    Allez, un truc amusant que je viens juste de découvrir:

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