J'ai été un peu surpris, donc je vais écrire un morceau de code et une brève explication.
sample.rb
class A
def a1
def a2
'a2'
end
'a1'
end
end
output1
irb(main):013:0> obj1 = A.new
=> #<A:0x00000002500198>
irb(main):014:0> obj1.a1
=> "a1"
irb(main):015:0> obj1.a2
=> "a2"
Comme vous pouvez le voir, l'appel à a1 définit dynamiquement a2 comme une méthode d'instance de A. Au fait, a2 n'existe que si a1 est appelé.
output2
irb(main):009:0> obj2 = A.new
=> #<A:0x000000011b7398>
irb(main):010:0> obj2.a2
NoMethodError: undefined method `a2' for #<A:0x000000011b7398>
from (irb):10
from /usr/bin/irb:11:in `<main>'
Puisque a2 est défini comme une méthode d'instance de A (car il est généralement référencé par des instances de A), il peut être appelé sur tous les objets jusqu'à ce que le programme se termine ou soit explicitement supprimé de A.
output3
irb(main):009:0> obj3 = A.new
=> #<A:0x00000001106f70>
irb(main):010:0> obj3.a1
=> "a1"
irb(main):011:0> obj3.a2
=> "a2"
irb(main):012:0> obj4 = A.new
=> #<A:0x00000001118888>
irb(main):013:0> obj4.a2
=> "a2"
À propos, cette histoire peut être trouvée dans Metaprogramming Ruby 2nd Edition, p111.
Serait-ce comme faire la même chose avec python?
sample.py
class A:
def a1(self):
self.__class__.a2 = lambda cls: 'a2'
return 'a1'
output4
>>> obj1 = A()
>>> obj1.a1()
'a1'
>>> obj1.a2()
'a2'
>>> obj2 = A()
>>> obj2.a2()
'a2'
Si tel est le cas, j'ai toujours l'impression de le faire de force et c'est sûr (?).