2016-10-25 2 views
0

У меня есть данные, такие как data = [[t1, t2, ...], [v1, v2, ...]]. Я хочу обернуть это в класс, поэтому я могу позвонить data.t вместо того, чтобы использовать data[0].Как перегрузить * оператор распаковки аргументов?

Я пытался сделать это с помощью следующих действий:

class Variable: 
    def __init__(self, data): 
     self.t = data[0] 
     self.v = data[1] 

    def __getitem__(self, key): 
     if key == 0: 
      return self.t 
     elif key == 1: 
      return self.v 
     else: 
      raise ValueError("not valid key '{}'".format(key)) 

    def __setitem__(self, key, value): 
     if key == 0: 
      self.t = value 
     elif key == 1: 
      self.v = value 
     else: 
      raise ValueError("not valid key '{}'".format(key)) 

Причины __getitem__ и __setitem__ перегрузки для обратной совместимости, так что data[0] работает до сих пор. Это работает для большинства вещей, но я столкнулся с проблемами со следующим вызовом:

func_that_takes_two_arguments(*data) # unpacking data 

Ошибки я получаю

/Users/pingul/Workspace/lhcfill/oml.py in __getitem__(self, key) 
    52         return self.val 
    53       else: 
---> 54         raise ValueError("not valid key  '{}'".format(key)) 
    55 
    56     def __setitem__(self, key, value): 
ValueError: not valid key '2' 

Как я могу сделать мой класс работать должным образом с аргументом распаковкой оператора?

+0

Вы не перегружаете '*', который просто выполняет итерацию над объектом. Вам нужно «поднять IndexError», а не «ValueError». – jonrsharpe

ответ

1

Оператор * выполняет итерацию по объекту. Эта итерация может быть выполнена с использованием только __getitem__(), но ваша реализация неисправна. Вместо этого, если вы поднимаете ValueError, вы должны выбросить IndexError, который сигнализирует о завершении итерации.

Смотрите также https://docs.python.org/3/reference/datamodel.html#object.getitem, который прямо заявляет

Примечание:for петли ожидать, что IndexError будет поднята незаконные индексы для обеспечения надлежащего обнаружения конца последовательности.

https://docs.python.org/2/library/functions.html#iter утверждает, что это называется «протоколом последовательности».

Смежные вопросы