如何解压一个对象,因为它是 for 循环中的一个元组?
How to unpack an object as it was a tuple in a for loop?
我尝试创建以下代码:
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return self
def __next__(self):
yield self.arg1, self.arg2, self.arg3
test_list = [Test(0), Test(1), Test(2)]
for arg1, arg2, arg3 in test_list:
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
但是当我尝试 运行 时,python 说:
Traceback (most recent call last):
File "test.py", line 20, in <module>
for arg1, arg2, arg3 in test_list:
ValueError: too many values to unpack (expected 3)
我可以通过手动解包来解决这个问题:
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
test_list = [Test(0), Test(1), Test(2)]
for test in test_list:
arg1, arg2, arg3 = test.arg1, test.arg2, test.arg3
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
我们如何解压 python 列表中的对象,而不是像解决方法所展示的那样显式执行?对于最后一个示例,结果如下:
arg1 1 arg2 2 arg3 3
arg1 2 arg2 3 arg3 4
arg1 3 arg2 4 arg3 5
问题是您的 __next__
方法未正确实施。您使 Test
class 可迭代,但它并没有按照您的想法进行迭代:
>>> itr = iter(Test(0))
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade9a8>
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade930>
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade9a8>
它不是生成 (self.arg1, self.arg2, self.arg3)
元组,而是生成生成器。这是由于您在 __next__
方法中使用 yield
引起的。 __next__
方法应该 return 值,而不是 yield 它们。有关详细说明和修复,请参阅 。
__next__
如果您有可变数量的项目到 return,则很有用。因为你有固定数量的属性从你的迭代器中产生,你可以简单地使用 iter
函数从三个属性创建一个迭代器并使 __iter__
方法成为迭代器 return :
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return iter((self.arg1, self.arg2, self.arg3))
相当于不使用 iter
函数:
class Test(object):
class Iter:
def __init__(self, lst):
self.lst = lst
self.index = 0
def __next__(self):
if self.index == len(self.lst):
raise StopIteration()
value = self.lst[self.index]
self.index += 1
return value
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return self.Iter((self.arg1, self.arg2, self.arg3))
Question: How to unpack an object as it was a tuple in a for loop?
你错了,你在循环中得到了一个Test(object)
。
要从对象中获取 tuple(arg1, arg2, arg3)
,您必须触发它。
使用 iter
:
class Test(object):
...
def __iter__(self):
yield self.arg1
yield self.arg2
yield self.arg3
for arg1, arg2, arg3 in map(iter, test_list):
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
或强制 .format(...
将 t
视为类型 tuple
:
for t in test_list:
print("arg1={}, arg2={}, arg3={}".format(*tuple(t)))
使用 class 属性 values(self, ...
:
class Test(object):
...
#@property
def values(self):
return self.arg1, self.arg2, self.arg3
for arg1, arg2, arg3 in map(Test.values, test_list):
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
或 .format(...
和 *
for t in test_list:
print("arg1={}, arg2={}, arg3={}".format(*t.values()))
推荐使用。没有任何 魔法:
for t in test_list:
print('arg1', t.arg1, 'arg2', t.arg2, 'arg3', t.arg3)
或 .format(...
for t in test_list:
print("arg1={t.arg1}, arg2={t.arg2}, arg3={t.arg3}".format(t=t))
测试 Python:3.5
你很接近,但是,你需要 yield
__iter__
方法中的值,而不是 __next__
方法中的值:
class Test:
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
yield from [self.arg1, self.arg2, self.arg3]
for a, b, c in [Test(0), Test(1), Test(2)]:
pass
yield self.arg1, self.arg2, self.arg3
将给出 tuple
结果 (1, 2, 3)
,当遍历列表时,需要额外的解包,即:
for [(a, b, c)] in [Test(0), Test(1), Test(2)]:
pass
因此,为了避免在循环中进行额外的解包,您必须通过遍历属性并一次生成一个生成值来创建一个生成值流。
我尝试创建以下代码:
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return self
def __next__(self):
yield self.arg1, self.arg2, self.arg3
test_list = [Test(0), Test(1), Test(2)]
for arg1, arg2, arg3 in test_list:
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
但是当我尝试 运行 时,python 说:
Traceback (most recent call last):
File "test.py", line 20, in <module>
for arg1, arg2, arg3 in test_list:
ValueError: too many values to unpack (expected 3)
我可以通过手动解包来解决这个问题:
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
test_list = [Test(0), Test(1), Test(2)]
for test in test_list:
arg1, arg2, arg3 = test.arg1, test.arg2, test.arg3
print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
我们如何解压 python 列表中的对象,而不是像解决方法所展示的那样显式执行?对于最后一个示例,结果如下:
arg1 1 arg2 2 arg3 3
arg1 2 arg2 3 arg3 4
arg1 3 arg2 4 arg3 5
问题是您的 __next__
方法未正确实施。您使 Test
class 可迭代,但它并没有按照您的想法进行迭代:
>>> itr = iter(Test(0))
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade9a8>
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade930>
>>> next(itr)
<generator object Test.__next__ at 0x7ff609ade9a8>
它不是生成 (self.arg1, self.arg2, self.arg3)
元组,而是生成生成器。这是由于您在 __next__
方法中使用 yield
引起的。 __next__
方法应该 return 值,而不是 yield 它们。有关详细说明和修复,请参阅
__next__
如果您有可变数量的项目到 return,则很有用。因为你有固定数量的属性从你的迭代器中产生,你可以简单地使用 iter
函数从三个属性创建一个迭代器并使 __iter__
方法成为迭代器 return :
class Test(object):
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return iter((self.arg1, self.arg2, self.arg3))
相当于不使用 iter
函数:
class Test(object):
class Iter:
def __init__(self, lst):
self.lst = lst
self.index = 0
def __next__(self):
if self.index == len(self.lst):
raise StopIteration()
value = self.lst[self.index]
self.index += 1
return value
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
return self.Iter((self.arg1, self.arg2, self.arg3))
Question: How to unpack an object as it was a tuple in a for loop?
你错了,你在循环中得到了一个Test(object)
。
要从对象中获取 tuple(arg1, arg2, arg3)
,您必须触发它。
使用
iter
:class Test(object): ... def __iter__(self): yield self.arg1 yield self.arg2 yield self.arg3 for arg1, arg2, arg3 in map(iter, test_list): print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
或强制
.format(...
将t
视为类型tuple
:for t in test_list: print("arg1={}, arg2={}, arg3={}".format(*tuple(t)))
使用 class 属性
values(self, ...
:class Test(object): ... #@property def values(self): return self.arg1, self.arg2, self.arg3 for arg1, arg2, arg3 in map(Test.values, test_list): print('arg1', arg1, 'arg2', arg2, 'arg3', arg3)
或
.format(...
和*
for t in test_list: print("arg1={}, arg2={}, arg3={}".format(*t.values()))
推荐使用。没有任何 魔法:
for t in test_list: print('arg1', t.arg1, 'arg2', t.arg2, 'arg3', t.arg3)
或
.format(...
for t in test_list: print("arg1={t.arg1}, arg2={t.arg2}, arg3={t.arg3}".format(t=t))
测试 Python:3.5
你很接近,但是,你需要 yield
__iter__
方法中的值,而不是 __next__
方法中的值:
class Test:
def __init__(self, arg):
self.arg1 = arg + 1
self.arg2 = arg + 2
self.arg3 = arg + 3
def __iter__(self):
yield from [self.arg1, self.arg2, self.arg3]
for a, b, c in [Test(0), Test(1), Test(2)]:
pass
yield self.arg1, self.arg2, self.arg3
将给出 tuple
结果 (1, 2, 3)
,当遍历列表时,需要额外的解包,即:
for [(a, b, c)] in [Test(0), Test(1), Test(2)]:
pass
因此,为了避免在循环中进行额外的解包,您必须通过遍历属性并一次生成一个生成值来创建一个生成值流。