To understand *args and **kwargs I made some searchs about, when I fell on this question *args and **kwargs?
The answer below the chosen answer caught my attention, which is this:
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print 'myfoo'
super(MyFoo, self).__init__(*args, **kwargs)
I tried some things on this example and running the code this way:
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print 'I think something is being called here'
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print args, kwargs
super(MyFoo, self).__init__(*args, **kwargs)
foo = MyFoo('Python', 2.7, stack='overflow')
I got this:
[...]
super(MyFoo, self).__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'stack'
Changing to be like super(MyFoo, self).__init__(args, kwargs)
the results are:
('Python', 2.7) {'stack': 'overflow'}
I think something is being called here
('Python', 2.7) {'stack': 'overflow'}
For some blow mind reasons I'm questioning this: what could be right and wrong in the example above? What would be allowed to do and what wouldn't in real life production?
Python is pretty flexible in terms of how arguments are passed to a function. The *args and **kwargs make it easier and cleaner to handle arguments. The important parts are “*” and “**”. You can use any word instead of args and kwargs but it is the common practice to use the words args and kwargs.
Kwargs allow you to pass keyword arguments to a function. They are used when you are not sure of the number of keyword arguments that will be passed in the function. Kwargs can be used for unpacking dictionary key, value pairs. This is done using the double asterisk notation ( ** ).
That dictionary is empty because you have not passed any kwargs in foo1. Note that you should only use variable x and y. Any other variables will cause error.
The *args and **kwargs keywords allow you to pass a variable number of arguments to a Python function. The *args keyword sends a list of values to a function. **kwargs sends a dictionary with values associated with keywords to a function. Both of these keywords introduce more flexibility into your code.
Your Foo.__init__()
does not support arbitrary keyword arguments. You can add **kw
to it's signature to make it accept them:
class Foo(object):
def __init__(self, value1, value2, **kw):
print 'I think something is being called here'
print value1, value2, kw
Keyword parameters are matched only with arguments with exact matching keyword names; your Foo
method would need to have Python
and stack
keyword parameters. If no matching keyword parameter are found but a **kw
parameter is, they are collected in that parameter instead.
If your subclass knows that the parent class only has positional arguments, you can always pass in positionals:
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print args, kwargs
while len(args) < 2:
args += kwargs.popitem()
super(MyFoo, self).__init__(*args[:2])
where you now must pass in two or more arguments to MyFoo
for the call to work.
In essence, super().methodname
returns a reference to the bound method; from there on out it is a normal method, so you need to pass in arguments that any method can accept. If your method doesn't accept keyword arguments, you get an exception.
When you do this:
super(MyFoo, self).__init__(*args, **kwargs)
It is the same as if you did this, base on how your code is working:
super(MyFoo, self).__init__("python", 2.7, stack="overflow")
However, the __init__
function of Foo
(from which MyFoo
inherits) doesn't support a keyword argument named "stack".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With