Как переписать метод __repr__ для уже созданного класса python - PullRequest
4 голосов
/ 30 апреля 2019

Я работаю со сторонней библиотекой, у которой плохое repr для класса, и я хотел бы перезаписать ее после создания экземпляра этого класса.

Я видел, как создавать связанные методы в существующем объекте.

class toy():
    pass

inst= toy()

class inhtoy():
    def __new__(cls,obj):
        def __repr__(self):
            return 'Sucessful'
        import types
        obj.__repr__ = types.MethodType(__repr__,obj)
        return obj

t = inhtoy(inst)

Действительно, если я вызову t. repr (), это сработает, однако не перезапишет исходный repr . Похоже, что <bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>> своего рода локальный метод.
Вызов repr(t) все еще указывает на исходное представление '<__main__.toy object at 0x7f76e0b61f98>', но не на перезаписанное.

Есть ли способ сделать это правильно?
Спасибо

Ответы [ 3 ]

2 голосов
/ 02 мая 2019

@ Ответ Nullman работает, потому что их решение на самом деле изменяет объект класса toy, который t является экземпляром, а не самим экземпляром, как ваш подход.

Специальный атрибут __class__ ссылается на объект класса, к которому принадлежит экземпляр.

print(t.__class__ is toy) # True

Итак, t.__class__.__repr__ = my_custom_repr присваивает __repr__ классу toy, а не экземпляру t.

Это становится видимым при сравнении вывода print(t.__repr__) между вашим подходом и подходом Нулмана.Предполагая, что функция уровня модуля __repr__ выглядит следующим образом:

def __repr__(self):
    return repr(self.__class__)

Ваше решение показывает:

<bound method __repr__ of <__main__.toy object at 0x00000000029E5A90>>

Обратите внимание, оно говорит __main__.toy object.
Решение Nullman показываетэто как:

<bound method __repr__ of <class '__main__.toy'>>

Когда вы вызываете t.__repr__(), используя свой подход, вы вызываете метод, который вы установили для экземпляра t, следовательно, он возвращает то, что вы сделали, он перенастроил;строка Success в вашем примере.
При использовании repr(), однако, class определяет вывод:

Класс можетуправляйте тем, что эта функция возвращает для своих экземпляров, определяя метод __repr__().

Как справедливо заметил Наллман, их подход изменит поведение всех существующих и будущих объектов,создается из toy.


Что касается странного имени, которое назначенный метод показывает при использовании вашего кода:

<bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>>

... это квалифицированное имя объекта функции, полученное из специального атрибута __qualname__.Это функция __repr__ из локальной области видимости метода вашего класса inhtoy __new__.
Кстати, прохождение вашего экземпляра inst через магический метод __new__ вашего inhtoy классане очень многого достиг.Ваш код функционально эквивалентен:

def __repr__(self):
    return "Success"

inst.__repr__ = types.MethodType(__repr__, obj)
1 голос
/ 30 апреля 2019

после некоторого осмотра я нашел этот ответ. способ сделать это на живом экземпляре:

t.__class__.__repr__ = my_custom_repr

обратите внимание, что это меняет все экземпляры класса , а не только этот экземпляр

0 голосов
/ 30 апреля 2019

Вы можете использовать наследование, чтобы создать новый класс, производный от класса интереса, а затем переопределить repr метод

class inhtoy(toy):

    def __init__(self):
        toy.__init__(self)

    def __repr__(self):
        # Your repr method
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...