Распаковка переменных экземпляра путем создания итерируемого контейнера

Я просто хочу иметь возможность распаковать переменные экземпляра класса foo, например:

x = foo("name", "999", "24", "0.222")
a, b, c, d = *x
a, b, c, d = [*x]

Я не уверен, какой метод является правильным для реализации моего собственного __iter__ Метод, однако, последний, который работал со смешанным "успехом". Я говорю смешанный, потому что выполнение с представленным кодом, кажется, изменяет исходный объект экземпляра x, так что это больше не действует.

class foo:
  def __init__(self, a, b, c, d):
    self.a = a
    self.b = b
    self.c = c
    self.d = d

  def __iter__(self):
    return iter([a, b, c, d])

Я прочитал множество постов на этом сайте относительно __iter__, __next__, генераторы и т. д., а также книгу по питону и docs.python.org и, кажется, не в состоянии понять, чего я не понимаю. Я понял, что __iter__ должен возвращать итеративный (который может быть просто self, но я не уверен, как это работает для того, что я хочу). Я также пробовал различные способы поиграть с реализацией __next__ и перебирая vars(foo).items()либо путем приведения к списку, либо в виде словаря, но безуспешно.

Я не верю, что это повторяющаяся запись, потому что единственные похожие вопросы, которые я видел, представляют один атрибут объекта последовательности списка или используют диапазон чисел вместо четырех неконтейнерных переменных.

2 ответа

Если вы хотите переменные экземпляра, вы должны получить к ним доступ с помощью .self:

def __iter__(self):
    return iter([self.a, self.b, self.c, self.d])

с этим изменением,

a, b, c, d = list(x)

вы получите переменные.


Вы можете перейти на более рискованный метод использования vars(x) или же x.__dict__отсортируйте его по имени переменной (и поэтому оно также ограничено, переменные сохранены в произвольном порядке) и извлеките второй элемент каждого кортежа. Но я бы сказал, что итератор определенно лучше.

Вы можете хранить аргументы в атрибуте (self.e ниже) или вернуть их при вызове функции:

class foo:
  def __init__(self, *args):
    self.a, self.b, self.c, self.d = self.e = args

  def __call__(self):
    return self.e

x = foo("name", "999", "24", "0.222")
a, b, c, d = x.e
# or
a, b, c, d = x()
Другие вопросы по тегам