[英]Are Python sets mutable?
Python 中的集合是否可变?
换句话说,如果我这样做:
x = set([1, 2, 3])
y = x
y |= set([4, 5, 6])
x
和y
是否仍然指向相同的 object,或者是否创建了一个新集合并将其分配给y
?
>>>> x = set([1, 2, 3])
>>>> y = x
>>>>
>>>> y |= set([4, 5, 6])
>>>> print x
set([1, 2, 3, 4, 5, 6])
>>>> print y
set([1, 2, 3, 4, 5, 6])
set1 = {1,2,3}
set2 = {1,2,[1,2]} --> unhashable type: 'list'
# Set elements should be immutable.
结论:集合是可变的。
你的两个问题是不同的。
Python 集是可变的吗?
是的:“可变”意味着您可以更改对象。 例如,整数是不可变的:您不能将数字1
更改为其他任何含义。 但是,您可以将元素添加到集合中,从而对其进行变异。
y = x; y |= {1,2,3}
吗y = x; y |= {1,2,3}
y = x; y |= {1,2,3}
改变x
?
是的。 代码y = x
表示“将名称y
绑定到名称x
当前表示的相同对象”。 代码y |= {1,2,3}
在y.__ior__({1,2,3})
调用了魔法方法y.__ior__({1,2,3})
,它改变了名称y
表示的对象。 由于这与x
表示的对象相同,因此您应该期望集合会发生变化。
您可以使用is
运算符检查两个名称是否完全指向同一个对象: x is y
仅当名称x
和y
表示的对象是同一个对象时。
如果要复制对象,通常的语法是y = x.copy()
或y = set(x)
。 然而,这只是一个浅拷贝:虽然它复制了集合对象,但并未复制所述对象的成员。 如果您想要copy.deepcopy(x)
,请使用copy.deepcopy(x)
。
Python 集分为两种类型。 可变的和不可变的。 使用 'set' 创建的集合是可变的,而使用 'frozenset' 创建的集合是不可变的。
>>> s = set(list('hello'))
>>> type(s)
<class 'set'>
以下方法适用于可变集。
s.add(item) -- 将项目添加到 s。 如果list
已经在 s list
则无效。
s.clear() -- 从 s 中删除所有项目。
s.difference_update(t) -- 从 s 中删除也在 t 中的所有项目。
s.discard(item) -- 从 s 中删除项目。 如果 item 不是 s 的成员,则什么都不会发生。
所有这些操作都会在适当的位置修改 set 。 参数 t 可以是任何支持迭代的对象。
更改集合后,甚至它们的对象引用也匹配。 我不知道为什么那本教科书说集合是不可变的。
>>> s1 ={1,2,3}
>>> id(s1)
140061513171016
>>> s1|={5,6,7}
>>> s1
{1, 2, 3, 5, 6, 7}
>>> id(s1)
140061513171016
print x,y
你会看到它们都指向同一个集合:
set([1, 2, 3, 4, 5, 6]) set([1, 2, 3, 4, 5, 6])
集合是可变的
s = {2,3,4,5,6}
type(s)
<class 'set'>
s.add(9)
s
{2, 3, 4, 5, 6, 9}
我们能够改变集合的元素
是的,Python 集合是可变的,因为我们可以在集合中添加、删除元素,但集合本身不能包含可变项。 像下面的代码会报错:
s = set([[1,2,3],[4,5,6]])
所以集合是可变的,但不能包含可变项,因为集合内部使用哈希表来存储其元素,因此集合元素需要是可哈希的。 但是像 list 这样的可变元素是不可散列的。
笔记:
可变元素不可散列
不可变元素是可散列的
就像字典的键不能是列表一样。
集合是可变的,您可以添加它们。 它们包含的项目可以是可变的,但它们必须是可清除的。 我在这篇文章中没有看到任何正确答案所以这是代码
class MyClass:
"""
This class is hashable, however, the hashes are
unique per instance not the data so a set will
have no way to determine equality
"""
def __init__(self):
self.my_attr = "no-unique-hash"
def __repr__(self):
return self.my_attr
class MyHashableClass:
"""
This object implements __hash__ and __eq__ and will
produce the same hash if the data is the same.
That way a set can remove equal objects.
"""
def __init__(self):
self.my_attr = "unique-hash"
def __hash__(self):
return hash(str(self))
def __eq__(self, other):
return hash(self) == hash(other)
def __repr__(self):
return self.my_attr
myclass_instance1 = MyClass()
myclass_instance2 = MyClass()
my_hashable_instance1 = MyHashableClass()
my_hashable_instance2 = MyHashableClass()
my_set = {
myclass_instance1,
myclass_instance2,
my_hashable_instance1,
my_hashable_instance2, # will be removed, not unique
} # sets can contain mutuable types
# The only objects set can not contain are objects
# with the __hash__=None, such as List, Dict, and Sets
print(my_set)
# prints {unique-hash, no-unique-hash, no-unique-hash }
my_hashable_instance1.my_attr = "new-hash" # mutating the object
# now that the hashes between the objects are differrent
# instance2 can be added
my_set.add(my_hashable_instance2)
print(my_set)
# {new-hash, no-unique-hash, no-unique-hash, unique-hash}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.