简体   繁体   中英

How to handle python inheritance properly

I've read the python documentation, but I still have questions about inheritance.

  • It seems in older versions of python you could pass arguments to super, but no longer. What if SuperClass does some sort of setup using its arguments?
  • If inheriting from object, should I call super? As far as I can tell, it doesn't make a functional difference.
  • Is this handled differently in python 2.7 vs. 3.x?

Is this how inheritance is supposed to be handled?

class SuperClass(object):
    def __init__(self, super_argument):
        super(object, self).__init__()
        self.super_argument = super_argument
        self.foo()

class ChildClass(SuperClass):
    def __init__(self, super_argument):
        self.super_argument = super_argument
        super(SuperClass, self).__init__()  

If so, does that make this an unworkable design for a class which might be inherited?

class SuperClass(object):
    def __init__(self, super_argument):
        super(object, self).__init__()
        self.foo(super_argument) # Argument passed instead without saving in self

It seems in older versions of python you could pass arguments to super, but no longer. What if SuperClass does some sort of setup using its arguments?

I think you've misunderstood which set of arguments you can leave out in 3.x. In Python 2.x, you needed to pass arguments to super to get the correctly-bound method:

class MyClass(...):

    def __init__(self, ...):
        super(MyClass, self).__init__(...)
            # ^ these arguments       ^ not these

In 3.x, you aren't required to supply those arguments, you can just call super().method(...) , but it will accept them just fine.

This is the same as the behaviour with inheriting object - you must do it to get a new-style class in 2.x, but 3.x will create a new-style class whether or not you explicitly inherit object .


Either way, you can pass arguments to the method on super . So if you're writing only for 3.x, you could do something like:

class MyClass(SuperClass):

    def __init__(self, super_arg, my_arg):
        super().__init__(super_arg)
            # ^ don't need these
                       # ^ still need these
        self.my_arg = my_arg

If inheriting from object, should I call super?

Yes, because you may be involved in multiple inheritance. Compare:

>>> class SuperClass1(object):
    def __init__(self):
        print("SuperClass1.__init__")


>>> class SuperClass2(object):
    def __init__(self):
        print("SuperClass2.__init__")


>>> class MyClass(SuperClass1, SuperClass2):
    def __init__(self):
        print("MyClass.__init__")
        super(MyClass, self).__init__()


>>> MyClass()
MyClass.__init__
SuperClass1.__init__
<__main__.MyClass object at 0x02D0CC50>

with:

>>> class SuperClass1(object):
    def __init__(self):
        print("SuperClass1.__init__")
        super(SuperClass1, self).__init__()


>>> class SuperClass2(object):
    def __init__(self):
        print("SuperClass2.__init__")
        super(SuperClass2, self).__init__()


>>> class MyClass(SuperClass1, SuperClass2):
    def __init__(self):
        print("MyClass.__init__")
        super(MyClass, self).__init__()


>>> MyClass()
MyClass.__init__
SuperClass1.__init__
SuperClass2.__init__
<__main__.MyClass object at 0x02BCDC10>

In the former, because SuperClass1 doesn't call super , SuperClass2.__init__ never gets reached.


Is this handled differently in python 2.7 vs. 3.x?

Hopefully this is now clear - you need to be more explicit in 2.x (or if you're writing code that should work in both versions) but otherwise the functionality is identical, and you should call super at all levels in both.

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