Jan Janáček
Jan Janáček

Reputation: 109

Inheriting keyword arguments using super(), but they are not listed untill specified in creating instance

I have some trouble grasping this, I guess pretty simple, concept. I am creating some tkinter app (not relevant), and I´m playing with inheriting attributes through super and *args, **kwargs:

class MainApp():

    def __init__(self, master = None, y = 10, x = "sample string"):
        self.master = master  
        self.y = y
        self.x = x
    # master is in the end root = tk.Tk(), 
    # which i pass as argument when creating that object, y and x are just for testing purpose

class Replica(MainApp):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        print(args)
        print(kw)
    # This is also just for testing how this stuff works, thing is;
    # When I run following code:


root = tk.Tk()
app = Replica(root)
print (app.x, app.y) # this returns ~ sample string 10; as expected
root.mainloop()

#But when output of print(args, kwargs) in Replica class __init__ method,
#it returns only (<tkinter.Tk object .>,) in printing args and empty dic
#{} in kwargs, therefore x and y werent considered either args or kwargs
# WHY?


#Well, but if i initialize Replica like this:

root = tk.Tk()
app = Replica(master = root, y = 5, x = "changed string")
root.mainloop()
# It returns empty tuple for args (), and full kwarg dic like this:
{'master': <tkinter.Tk object .>, 'y': 2, 'x': 'changed string'}

# In same logic, if I initiate Replica like this:


app = Replica(root, 10, "changed string")
# This returns all attributes in args, therefore print(args) in __init__
# method returns (<tkinter.Tk object .>, 10, 'changed string') 
# and kwargs are empty {}

# Similiarly, when running this:
app = Replica(root, 10, x = "changed string")
# It shifts x to kwargs dictionary and return is
# (<tkinter.Tk object .>, 10) and {'x': 'changed string'}

I mean I kind of understand what is going on, Im not blind, but still wonder, why master, y and x are not inherited as kwargs immediatly, after all, they are keyword arguments in MainApp init method. I would assume super() method will take care of that. Application works fine but I am kind of frustrated from not understanding this and would appreciate some insight.

How is x and y attribute inherited when..

def __init__(self, *args, **kwargs)
    super().__init__(*args, **kwargs) 

.. does not specify x or y. And even when runnin this:

def __init__(self, master):
    super().__init__(master)

It runs fine and inherits x and y attributes..

Once again, I would appreciate some insight, thank you.

Upvotes: 1

Views: 216

Answers (1)

Alex Hall
Alex Hall

Reputation: 36033

This has nothing to do with super or inheritance. It's just parameters taking on their default values when no arguments are passed. Here's a simple example:

def foo(x=5):
  print('foo: x =', x)

def bar(*args, **kwargs):
  print('bar:', args, kwargs)
  foo(**kwargs)

bar()
bar(x=2)

Output:

bar: () {}
foo: x = 5
bar: () {'x': 2}
foo: x = 2

Demo

args and kwargs are the values that are passed to bar, and in the end the same values are passed to foo. If nothing gets passed to bar, then nothing is passed to foo, and the default values are used.

super().__init__(*args, **kw) is equivalent to MainApp.__init__(*args, **kw). The default values aren't being 'inherited', they're just being used as normal.

Upvotes: 1

Related Questions