繁体   English   中英

Python 组是可变的吗?

[英]Are Python sets mutable?

Python 中的集合是否可变?


换句话说,如果我这样做:

x = set([1, 2, 3])
y = x

y |= set([4, 5, 6])

xy是否仍然指向相同的 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仅当名称xy表示的对象是同一个对象时。

如果要复制对象,通常的语法是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}

我不认为 Python 集是可变的,正如在“ Mark Lutz 的Learning Python 5th Edition - O'Reilly Publications 》”一书中明确提到的那样

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM