我想在python中创建一组namedtuple
,能够使用union操作动态添加元素。
以下代码段创建了set
namedtuple
,表现良好。
from collections import namedtuple
B = namedtuple('B', 'name x')
b1 = B('b1',90)
b2 = B('b2',92)
s = set([b1,b2])
print(s)
打印
{B(name='b1', x=90), B(name='b2', x=92)}
现在,如果我创建了另一个namedtuple
并使用set
操作将其添加到我的union
,则表明其行为不符合预期。
b3 = B('b3',93)
s = s.union(b3)
print(s)
代码段打印以下输出。
{93, B(name='b1', x=90), B(name='b2', x=92), 'b3'}
预期输出应为:
{B(name='b1', x=90), B(name='b2', x=92), B(name='b3', x=93)}
我误解了API吗? python2和3都显示相同的行为。
答案 0 :(得分:4)
namedtuple
实例是一个可迭代的项目。 set.union
只是将当前集合与namedtuple
中的项目合并。
但是,您想要的是将namedtuple
放在另一个容器/ iterable中,因此合并是使用新的父迭代中包含的项(namedtuple
)完成的:
s.union((b3,))
如果您真正想到运算符等价物,那就更明显了:
s = s | set(b3) # set(b3) -> {93, 'b3'}
与我们实际想要的相比:
s = s | {b3}
使用外部iterable执行 union 。
答案 1 :(得分:2)
union
需要一个集合(或列表或其他可迭代的),但是您传递一个命名元组,它本身是一个可迭代的,但它提供了值,因此您将该值与值合并。试试这个:
s = s.union({b3})
答案 2 :(得分:1)
由于b3
是可迭代的,union
对其元素而不是元组本身起作用。将其替换为:
s = s.union([b3])
答案 3 :(得分:0)
set.union
上的文档实际上解释了这一点:
@foreach($course->users->excercises as $excercise) {{ $excercise->pivot->grade }} @endforeach
使用集合中的元素和所有其他元素返回一个新集合。
因此,它将创建一个包含union(*others)
:
others
在您的情况下(因为您将其分配回>>> set(b3) # these are the unique elements in your `b3`
{93, 'b3'}
>>> s.union(b3) # the union of the unique elements in "s" and "b3"
{B(name='b1', x=90), 93, 'b3', B(name='b2', x=92)}
),您只需添加项目,从而避免完全创建新集:
s