python 集合并集操作在命名元组中表现不佳
python set union operation is not behaving well with named tuples
我想在 python 中创建一组 namedtuple
,能够使用联合操作动态添加元素。
以下代码片段创建了 namedtuple
的 set
,表现良好。
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
并使用 union
操作将其添加到我的 set
,它不会按预期运行。
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 都表现出相同的行为。
union
需要一个集合(或列表或另一个可迭代对象),但您传递了一个命名元组,它本身就是一个可迭代对象,但它提供了值,因此您将集合与值合并。试试这个:
s = s.union({b3})
一个namedtuple
实例是一个可迭代的项目。 set.union
只是将当前集合与 namedtuple
中的项目合并。
但是,您想要的是将 namedtuple
放入另一个 container/iterable,因此合并是使用包含在新父可迭代项中的项目(namedtuple
)完成的:
s.union((b3,))
如果你真的想到等价的运算符就更明显了:
s = s | set(b3) # set(b3) -> {93, 'b3'}
与我们实际想要的相比:
s = s | {b3}
union 与外部迭代一起执行。
因为 b3
是可迭代的,所以 union
作用于它的元素而不是元组本身。将其替换为:
s = s.union([b3])
set.union
上的文档实际上是这样解释的:
union(*others)
Return a new set with elements from the set and all 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
)你可以简单地添加项目从而避免完全创建一个新的集合:
>>> s.add(b3)
>>> s
{B(name='b1', x=90), B(name='b3', x=93), B(name='b2', x=92)}
我想在 python 中创建一组 namedtuple
,能够使用联合操作动态添加元素。
以下代码片段创建了 namedtuple
的 set
,表现良好。
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
并使用 union
操作将其添加到我的 set
,它不会按预期运行。
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 都表现出相同的行为。
union
需要一个集合(或列表或另一个可迭代对象),但您传递了一个命名元组,它本身就是一个可迭代对象,但它提供了值,因此您将集合与值合并。试试这个:
s = s.union({b3})
一个namedtuple
实例是一个可迭代的项目。 set.union
只是将当前集合与 namedtuple
中的项目合并。
但是,您想要的是将 namedtuple
放入另一个 container/iterable,因此合并是使用包含在新父可迭代项中的项目(namedtuple
)完成的:
s.union((b3,))
如果你真的想到等价的运算符就更明显了:
s = s | set(b3) # set(b3) -> {93, 'b3'}
与我们实际想要的相比:
s = s | {b3}
union 与外部迭代一起执行。
因为 b3
是可迭代的,所以 union
作用于它的元素而不是元组本身。将其替换为:
s = s.union([b3])
set.union
上的文档实际上是这样解释的:
union(*others)
Return a new set with elements from the set and all 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
)你可以简单地添加项目从而避免完全创建一个新的集合:
>>> s.add(b3)
>>> s
{B(name='b1', x=90), B(name='b3', x=93), B(name='b2', x=92)}