Overriding special methods on an instance

后端 未结 5 1705
独厮守ぢ
独厮守ぢ 2020-11-22 03:36

I hope someone can answer this that has a good deep understanding of Python :)

Consider the following code:

>>> class A(object):
...     pas         


        
5条回答
  •  粉色の甜心
    2020-11-22 03:52

    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.

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


    Things are slightly different in 2.x, mostly because of the presence of classic classes, but as long as you're only creating new-style classes you can think of them as the same.


    The most common reason people want to do this is to monkey-patch different instances of an object to do different things. You can't do that with special methods, so… what can you do? There's a clean solution, and a hacky solution.

    The clean solution is to implement a special method on the class that just calls a regular method on the instance. Then you can monkey patch that regular method on each instance. For example:

    class C(object):
        def __repr__(self):
            return getattr(self, '_repr')()
        def _repr(self):
            return 'Boring: {}'.format(object.__repr__(self))
    
    c = C()
    def c_repr(self):
        return "It's-a me, c_repr: {}".format(object.__repr__(self))
    c._repr = c_repr.__get__(c)
    

    The hacky solution is to build a new subclass on the fly and re-class the object. I suspect anyone who really has a situation where this is a good idea will know how to implement it from that sentence, and anyone who doesn't know how to do so shouldn't be trying, so I'll leave it at that.

提交回复
热议问题