0

Я просто хочу, чтобы иметь возможность распаковывать переменный экземпляр класса Foo, например:Распаковка переменного экземпляра, сделав контейнер Iterable

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() либо путем литья в список, либо как словарь, без успеха.

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

+0

Что заставляет вас думать, возвращающая список из '' __iter__' изменяет x'? Если что-то итерация над ним меняет 'a' и т. Д., Тогда' x' будет меняться * однако * вы реализуете итератор. Не могли бы вы просто сделать это «Последовательность» (т. Е. Реализовать «__getitem__» и «__len__' за https://docs.python.org/3/library/collections.abc.html)? – jonrsharpe

+0

Ваша первая распаковка отсутствует, в конце концов, запятая. Кроме того, не могли бы вы уточнить «изменить исходный экземпляр объекта« x »? Как так? –

+0

@jonrsharpe Я предположил, что я возвращаю итератор для явно определенного списка (т. Е. Позволяя повторять переменные экземпляра obj как обычный список - и распаковывать аналогично). Я могу попытаться сделать это Sequence уверенным, это просто займет больше времени. Я определенно ценю этот ресурс и проверю его. @Jim Fasarakis-Hilliard, как в настоящее время реализовано, если я попытаюсь сделать, скажем: 'a, b, c, d = * x,' a, b, c и d будут содержать правильные значения, но затем любая попытка доступа x - как и до распаковки - рейзы "Объект TypeError: 'float' не подлежит индексированию" – Todd

ответ

1

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

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

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

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

поможет вам переменные.


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

1

Вы можете хранить аргументы в атрибуте (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() 

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

  • Нет связанных вопросов^_^