开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜