Это динамически определяет новый класс GentlePerson
и переназначение p
«s класс к нему:
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"
По Вашему запросу, это изменяет p
» s, но не изменяет класс p
Person
. Таким образом, другие экземпляры Person
не затронуты (и поднимут AttributeError
, если были вызваны introduce_self
).
Хотя это не было прямой вопрос в вопросе, я добавлю для Googlers и любопытных, что также можно динамически изменять базы относится к классу, но (AFAIK) только если класс не наследует напрямую от 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
Зачем это делать без комментариев? Может быть, потому что слово Ruby появляется в тексте? oO –
Uuuuurrgghhh !!!!! Изменение экземпляра без изменения класса - это рецепт катастрофы. Более удобный способ сделать это - сделать подкласс «Человек» и смешать «Джентльмен» с этим. – katrielalex
@katrielalex: Вероятно, вы правы в большинстве случаев. Тем не менее, мне нужна эта функциональность, потому что я хочу добавить функциональность в стороннюю библиотеку, интерфейс которой я не могу изменить. Мне пришлось выбирать между mixins или прокси-шаблоном, из которых последнее мне не очень нравится. –