Interchange of Position of Two Keyword Arguments Throws Error
I have an odd problem. I know that in Python, kwargs follow args, so I checked for that and it's not the problem. What is the problem is this:
Fine:
def __init__(self, sample_rate, label=u"", data=[] ):
TypeError: __init__()
got multiple values for keyword argument 'data':
def __init__(self, sample_ra开发者_运维百科te, data=[], label=u""):
The calling line that throws the error looks like this:
def __getslice__(self, start, stop):
return Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))
The full code:
class Channel(list):
sample_rate = 0
def __init__(self, sample_rate, data=[], label=u"" ):
list.__init__(self,data)
self.sample_rate = sample_rate
self.label = label
@property
def nyquist_rate(self):
return float(self.sample_rate) / 2.0
def __getslice__(self, start, stop):
return Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))
Thank you!
In the second version (def __init__(self, sample_rate, data=[], label=u""):
), the second positional argument (when called, that means not counting self
) is data
, but in __getslice__
, the second argument that you pass is label
. So you should either keep label as the second argument, or change the function call to this:
return Channel(self.sample_rate, label=self.label, data=list.__getslice__(self,start,stop))
You are calling the code with
Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))
Note that the second parameter has no keyword, so the interpreter assumes this is the data
parameter (because that's the order they are defined in the function). If you add label=
it should solve it.
But, you have a more important error in your code: Never use [] as a default value. The reason is this code is evaluated at function definition time. every time you call this code with no data
parameter, you'll get the same list as a default value. and it might not be empty after the first time! This is true for all mutable datatypes. The correct way to do this, is to use None
as a default value and inside the function (code that runs each time) init a new [], if the parameter value is None.
(This gocha is also explained well by David Goodger, in Default Parameter Values)
The problem is that in your calling code, you have two positional arguments:
return Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))
# sample_rate (pos) data (pos) data (kw)
In Python 2.x, there is no distinction between positional and keyword arguments in the function definition. When a function is called, positional arguments from the function invocation are used to fill arguments left to right, then all keyword arguments are bound. In your case, data
is bound both by a positional and a keyword arguments. It works in the other case because then the second positional argument is used for label
, and data
only gets the keyword argument.
精彩评论