7

Where is python getting the repr which is still yielding 'foo' even after the original repr method has been overwritten?

class Test(object):
    def __init__(self, name, number_array): 
        self.name = name
        self.number_array = number_array
    def __repr__(self):
        return str(self.name) 

def custom_repr(self): 
    return str(self.name*4)

>>> A = Test('foo', [1,2])
>>> A
foo
>>> A.__repr__ = custom_repr.__get__(A, A.__class__)
>>>A.__repr__()
foofoofoofoo
>>>A
foo
user3467349
  • 3,043
  • 4
  • 34
  • 61
  • No, you're right, I think it is a duplicate, only your way of asking it is a little bit less to the point - so i couldn't tell right away :) – user3467349 Sep 26 '14 at 01:27
  • You're right that it's a dup, but I really don't love the answer there. It doesn't link to the docs, it speculates (incorrectly) about the rationale, it makes it sound like Python guarantees that all special methods are always looked up on the class… so I copied my answer over there. – abarnert Sep 26 '14 at 01:31
  • PS, did you lose your comment upvote rep when the dup comment got auto-deleted? (Not hugely important, but I'm mildly curious.) – abarnert Sep 26 '14 at 01:40
  • I still have +15, not sure about the in between, I'm not all that familiar with how the rep system works. – user3467349 Sep 26 '14 at 01:54

2 Answers2

5

As explained in Special Method Lookup:

For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary … In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass

(The part I've snipped out explains the rationale behind this, if you're interested in that.)

Python doesn't document exactly when an implementation should or shouldn't look up the method on the type; all it documents is, in effect, that implementations may or may not look at the instance for special method lookups, so you shouldn't count on either.

But, as you can guess from your test results, in the CPython implementation, __repr__ is one of the functions looked up on the type.

abarnert
  • 354,177
  • 51
  • 601
  • 671
1

__repr__ is looked up directly on the class, not on the instance, when it's looked up by repr or similar (such as when it's called by the interactive interpreter). If you must monkey-patch a repr, do it on the class (but please don't).

This same basic rule applies to most dunder methods.

Mike Graham
  • 73,987
  • 14
  • 101
  • 130
  • so you mean it's impossible to dynamically add a __repr__ method in that case? – user3467349 Sep 26 '14 at 01:24
  • @user3467349, adding it to the instance does not work. (If you must monkey-patch a new `__repr__` for a specific instance (and please feel free *not* to do so), do so on the class, special-casing the instance with `is`.) – Mike Graham Sep 26 '14 at 01:26
  • Unfortunately that will monkey-patch every object of the class, which really wasn't what I was going for. – user3467349 Sep 26 '14 at 01:30
  • @user3467349, Yes, as noted, you can only monkey-patch it on the class. However you *can* have the *same effect* by special-casing the instance in the new `__repr__` (not that that is recommended). – Mike Graham Sep 27 '14 at 14:40