简体   繁体   中英

Difference between super(Foo, self) and super(Foo, self.__class__)?

I'm extremely new to python, so hopefully I'm not missing too much requisite knowledge to understand this, but...

I have a class with some properties, and I'm trying overriding the setter on one of them similar to this example:

class Foo(object):
    def __init__(self):
        self._x = True

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

class Bar(Foo):
    @property
    def x(self):
        return super().x

    @x.setter
    def x(self, value):
        print('x set')

        super(Bar, self.__class__).x.fset(self, value)

bar = Bar()

# Prints 'x set' as expected:
bar.x = True

This works fine, but I really don't understand why this line works the way it does...

super(Bar, self.__class__).x.fset(self, value)

...and how it differs from this line, which doesn't work:

super(Bar, self).x.fset(self, value)

Any guidance would be appreciated.

To simplify things, we'll assume (as in your example) that super always returns a proxy for something defined in Foo , that is, there are no other classes involved.

  1. Ignore the call to super for the moment, consider the difference between bar.x and Bar.x . The first would invoke the getter for the named property; the latter is just a reference to the property itself.

  2. Now consider a non-property attribute. super(Bar, self).method would be an instance of a bound method, such that super(Bar, self).method(x) would be equivalent to Foo.method(self, x) . super(Bar, self.__class__).method , however, would be the unbound method, ie simply Foo.method .

  3. Now combine steps 1 and 2. We know that bar.x will cause the getter defined in Bar to be called, and we know that super(Bar, self) is a proxy for Foo via self . Therefore, super(Bar, self).x must call the getter defined not in Bar , but in Foo .

    We also know that Bar.x is simply a reference to a property object, one that doesn't invoke its getter; and we know that super(Bar, self.__class__) acts as a proxy for Foo independent of any particular object. Therefore, we can conclude that super(Bar, self.__class__).x , for an instance self of Bar , is a reference to the property object defined in Foo .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM