In your example code, Child1's design is very fragile. If its two base classes share some common base (and call their own parents' __init__ method inside of their own turn), that grandparent class might get initialized more than once, which would be bad if it's computationally costly, or has side effects. This is the "diamond pattern" of inheritance hierarchy that can be troublesome in many languages (like C++) that allow multiple inheritance.
Here's an example of the bad problem that can come up with explicit parent calls, and which super() is designed to fix:
class Grandparent:
    def __init__(self):
        print("Grandparent")
class Parent1(Grandparent):
    def __init__(self):
        print("Parent1")
        Grandparent.__init__(self)
class Parent2(Grandparent):
    def __init__(self):
        print("Parent2")
        Grandparent.__init__(self)
class Child(Parent1, Parent2):
    def __init__(self):
        print("Child")
        Parent1.__init__(self)
        Parent2.__init__(self)
c = Child() # this causes "Grandparent" to be printed twice!
Python's solution is to use super() which allows collaborative multiple inheritance. Each class must be set up to use it, including the intermediate base classes! Once you set everything up to use super, they'll call each other as necessary, and nothing will ever get called more than once.
class Grandparent:
    def __init__(self):
        print("Grandparent")
class Parent1(Grandparent):
    def __init__(self):
        print("Parent1")
        super().__init__()
class Parent2(Grandparent):
    def __init__(self):
        print("Parent2")
        super().__init__()
class Child(Parent1, Parent2):
    def __init__(self):
        print("Child")
        super().__init__()
c = Child() # no extra "Grandparent" printout this time
In fact, every instance of multiple-inheritance in Python is a diamond shape, with the Grandparent class of object (if not something else). The object class has an __init__ method that takes no arguments (other than self) and does nothing.
It's important to note that the super().__init__ calls from the ParentX classes don't always go directly to Grandparent. When initializing an instance of Parent1 or Parent2, they will, but when instantiating an instance of Child, then Parent1.__init__'s call will go to Parent2.__init__, and only from there will Parent2's super call go to Grandparent.__init__.
Where a super call resolves to depends on the MRO (Method Resolution Order) of the instance the methods are being called on. A super call generally means "find this method in the next class in the MRO" relative to where it's called from. You can see the MRO of a class by calling SomeClass.mro(). For Child in my examples, it's: [Child, Parent1, Parent2, Grandparent,  object]