4
votes

Comment écraser la méthode __repr__ pour une classe python déjà instanciée

Je travaille avec une bibliothèque tierce qui a une mauvaise repr pour une classe et je voudrais l'écraser une fois qu'une instance de cette classe a été créée.

J'ai vu comment créer des méthodes liées dans un objet existant.

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)

En effet, si j'appelle t. repr () ça marche, cependant ça n'écrase pas l'original repr . Il apparaît comme .__ repr__ of <__ main __. toy object at>> une sorte de méthode locale.
L'appel de repr (t) pointe toujours vers la représentation d'origine '<__ main __. toy object at>' mais pas celle écrasée.

Y a-t-il un moyen de le faire correctement?
Merci


3 commentaires

Aussi mauvais que soit leur __repr__ , le remplacer par un substitut de votre choix sera encore plus déroutant.


alors que je voudrais également savoir comment faire cela à une instance en direct, pourquoi ne pas sous-classer leur classe et simplement changer le __repr__ ?


@Nullman Parce que le sous-classement obligerait l'utilisateur à en hériter. Cela changerait également le nom de la classe générant des incompatibilités avec la bibliothèque tierce. La modification de l'objet conserve tout le même.


3 Réponses :


1
votes

après quelques recherches, j'ai trouvé cette réponse. la façon de le faire est sur une instance en direct est:

t.__class__.__repr__ = my_custom_repr

veuillez noter que cela change toutes les instances de classe et pas seulement cette instance

p >


3 commentaires

Eh bien, dans mon but, cela fonctionnera. Savez-vous pourquoi cela fonctionne de cette façon?


malheureusement non, mais si vous le comprenez, je serais heureux si vous me le faites savoir


@Nullman J'ai ajouté une réponse pour tenter d'expliquer pourquoi vos solutions fonctionnent et que l'OP ne fonctionne pas; au cas où vous seriez toujours intéressé ...



0
votes

Vous pouvez utiliser l'héritage pour créer une nouvelle classe dérivée de la classe d'intérêt, puis remplacer la méthode repr

class inhtoy(toy):

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

    def __repr__(self):
        # Your repr method


0 commentaires

3
votes

La réponse de

@ Nullman fonctionne, car leur solution est en fait de changer l'objet de classe toy , dont t est une instance, pas l'instance elle-même, comme le fait votre approche.

L'attribut spécial __class__ a> fait référence à l'objet de classe auquel appartient une instance.

def __repr__(self):
    return "Success"

inst.__repr__ = types.MethodType(__repr__, obj)

Ainsi, t .__ class __.__ repr__ = my_custom_repr assigne à __repr __ code> sur la classe toy , pas sur l'instance t.

Ceci devient visible lors de la comparaison de la sortie de print (t .__ repr__ ) entre votre approche et celle de Nullman. En supposant qu'une fonction au niveau du module __repr__ ressemble à ceci:

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

Votre solution montre:

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

Remarque, il dit __main __. objet jouet .
La solution de Nullman l'affiche comme:

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

Lorsque vous appelez t .__ repr __ () en utilisant votre approche, vous appelez la méthode que vous avez définie sur l'instance t , donc elle renvoie ce que vous lui avez fait relancer; la chaîne Success dans votre exemple.
Lors de l'utilisation de repr () , cependant, la classe définit la sortie:

Une classe peut contrôler ce que cette fonction renvoie pour ses instances en définir une méthode __repr __ () .

Comme Nullman l'a souligné à juste titre, leur approche modifiera le comportement de tous les objets et futurs existants, instanciés à partir de toy .


En ce qui concerne le nom étrange, que la méthode assignée montre lors de l'utilisation de votre code:

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

... c'est la fonction nom qualifié provenant du __qualname__ attribut spécial. C'est la fonction __repr__ de la portée locale de la méthode __new__ de votre classe inhtoy .
En parlant de cela, passer votre instance inst via la méthode magique __new__ de votre classe inhtoy ne permet pas vraiment de faire grand-chose. Votre code est fonctionnellement équivalent à:

print(t.__class__ is toy) # True


0 commentaires