Questo definisce dinamicamente una nuova classe GentlePerson
, e riassegna p
's classe ad esso:
class Gentleman(object):
def introduce_self(self):
return "Hello, my name is %s" % self.name
class Person(object):
def __init__(self, name):
self.name = name
p = Person("John")
p.__class__ = type('GentlePerson',(Person,Gentleman),{})
print(p.introduce_self())
# "Hello, my name is John"
Per la richiesta, questa modifica p
' s basi, ma non modifica la classe originale . Pertanto, altre istanze di Person
non sono interessate (e potrebbero generare un AttributeError
se sono stati chiamati introduce_self
).
Anche se non è stato chiesto direttamente nella questione, aggiungerò per Googler e curiosi, che è anche possibile cambiare dinamicamente le basi di una classe, ma (per quanto ne so) solo se la classe non eredita direttamente da object
:
class Gentleman(object):
def introduce_self(self):
return "Hello, my name is %s" % self.name
class Base(object):pass
class Person(Base):
def __init__(self, name):
self.name = name
p = Person("John")
Person.__bases__=(Gentleman,object,)
print(p.introduce_self())
# "Hello, my name is John"
q = Person("Pete")
print(q.introduce_self())
# Hello, my name is Pete
Perché downvotare questo senza un commento? Forse perché la parola Ruby appare nel testo? oO –
Uuuuurrgghhh !!!!! Cambiare un'istanza senza cambiare la classe è una ricetta per il disastro. Il modo migliore per farlo è creare una sottoclasse di 'Person' e mescolare' Gentleman' in quello. – katrielalex
@katrielalex: Probabilmente hai ragione nella maggior parte dei casi. Tuttavia, ho bisogno di questa funzionalità perché voglio aggiungere funzionalità a una libreria di terze parti la cui interfaccia non può essere modificata. Dovevo scegliere tra mixins o il pattern proxy, di cui quest'ultimo non mi piace molto. –