class Pen(object):
def __init__(self, mean_radius = None, length = None):
self.usage = "Is used to apply ink trails to drawing surfaces"
self.mean_radius = mean_radius
self.length = length
class FountainPen(Pen):
def __init__(self, manufacturer = "Waterman", *args, **kwargs):
Pen.__init__(self, *args, **kwargs)
self.manufacturer = manufacturer
self.cartridge_state = "non-empty"
>>> instance_FP = FountainPen(5, 1)
>>> instance_FP.mean_radius
>>> print instance_FP.mean_radius
1
>>> print instance_FP.length
None
What happens with the integer 5
being passed as an argument in the instantiation of FountainPen
? Why does print instance_FP.mean_radius
return 1
and not 5
?
You have to think it like that: *args
and **kwargs
"eat" all the positional/keyword arguments left by the "regular" arguments that precede them. If you put them in the end, they will only get whatever couldn't fit the "regular arguments".
So, when you write FountainPen(5,1)
what happens is that FountainPen.__init__
gets called like this:
self
is set to the newly created instance; manufacturer
gets the first argument, which is 5; *args
"eats" all the remaining positional arguments, ie just 1
; so args
is now set to [1]
; *kwargs
would eat any keyword argument left, but there's none, so it becomes {}
. It's then clear that Pen.__init__
is called with just 1
as argument (besides self
), and length
remains set to its default value ( None
).
Matteo Italia 's mentions what is wrong, basically manufacturer
is a positional argument. You can fix it by slightly changing FountainPen
's __init__
to the following:
def __init__(self, *args, manufacturer = "Waterman", **kwargs):
Doing this will make manufacturer
a keyword argument so to change it you will have to call:
FountainPen(manufacturer="newval")
Note: Unfortunately this syntax (of having keyword only arguments after the *args
parameter) is only valid in Python 3. Jon Clements has a solution that solves this problem for Python 2.
A more elegant solution would be:
class FountainPen(Pen):
def __init__(self, *args, **kwargs):
Pen.__init__(self, *args, **kwargs)
self.manufacturer = kwargs.get('manufacturer', 'Waterman')
self.cartridge_state = "non-empty"
blah = FountainPen(5, 1, manufacturer='Waterman')
In your code 5 is assigned to the argument manufacturer
and 1 goes to *args
.
When passing arguments without keys to a function, you must first provide the explicit ones. The rest is passed to *args. To avoid this, provide keywords when calling your constructor:
>>> instance_FP = FountainPen(mean_radius=5, length=1)
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.