Обмен позициями двух аргументов ключевого слова вызывает ошибку

У меня странная проблема. Я знаю, что в Python kwargs следуют за аргументами, поэтому я проверил это, и это не проблема. В чем проблема вот в чем:

Отлично:

def __init__(self, sample_rate, label=u"", data=[] ):

TypeError: __init__() получил несколько значений аргумента ключевого слова «данные»:

def __init__(self, sample_rate, data=[], label=u""):

Строка вызова, которая выдает ошибку, выглядит так:

def __getslice__(self, start, stop):
    return Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))

Полный код:

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))

Благодарю вас!


person SapphireSun    schedule 10.02.2010    source источник


Ответы (3)


Во второй версии (def __init__(self, sample_rate, data=[], label=u""):) вторым позиционным аргументом (при вызове это означает, что не считается self) является data, но в __getslice__ вторым аргументом, который вы передаете, является label. Таким образом, вы должны либо сохранить метку в качестве второго аргумента, либо изменить вызов функции на это:

return Channel(self.sample_rate, label=self.label, data=list.__getslice__(self,start,stop))
person sttwister    schedule 10.02.2010
comment
Ба! Яркий пример того, почему я не должен программировать в 4 утра. Спасибо всем за то, что потрудились поймать мои глупые ошибки. - person SapphireSun; 10.02.2010

Вы вызываете код с помощью

Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))

Обратите внимание, что у второго параметра нет ключевого слова, поэтому интерпретатор предполагает, что это параметр data (поскольку именно в таком порядке они определены в функции). Если вы добавите label=, это должно решить эту проблему.

Но в вашем коде есть более важная ошибка: Никогда не используйте [] в качестве значения по умолчанию. Причина в том, что этот код оценивается во время определения функции. каждый раз, когда вы вызываете этот код без параметра data, вы получите тот же список, что и значение по умолчанию. и он не может быть пустым после первого раза! Это верно для всех изменяемых типов данных. Правильный способ сделать это — использовать None в качестве значения по умолчанию и внутри функции (код, который запускается каждый раз) инициализировать новый [], если значение параметра равно None. (Эта гоча также хорошо объяснена Дэвидом Гуджером в Значения параметров по умолчанию)

person Ofri Raviv    schedule 10.02.2010

Проблема в том, что в вашем вызывающем коде у вас есть два позиционных аргумента:

return Channel(self.sample_rate, self.label, data=list.__getslice__(self,start,stop))
#              sample_rate (pos) data (pos)  data (kw)

В Python 2.x нет различия между позиционными и ключевыми аргументами в определении функции. Когда вызывается функция, позиционные аргументы из вызова функции используются для заполнения аргументов слева направо, затем все аргументы ключевого слова связываются. В вашем случае data связан как позиционными, так и ключевыми аргументами. Это работает в другом случае, потому что тогда второй позиционный аргумент используется для label, а data получает только аргумент ключевого слова.

person Torsten Marek    schedule 10.02.2010