You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python集合中同时存储1、0、True、False及其他值

如何在Python集合中同时存储1、0、True、False及其他值

嘿,这个问题我之前也碰到过!因为在Python里,True其实是int的子类,True == 1和False == 0都会返回True,而且它们的哈希值也完全一样,所以集合会把它们判定为重复元素,自动去重。要同时保留这四个值,得想办法让集合把它们当成不同的元素,这里有两个实用的办法:

  • 用自定义包装类区分类型和值
    我们可以写一个简单的类,把每个值包起来,通过重写__eq__和__hash__方法,让集合判断元素是否重复的时候,同时考虑值的类型和内容。这样1(int类型)和True(bool类型)就会被当成不同的元素了:

    class WrappedVal:
        def __init__(self, val):
            self.val = val
        def __eq__(self, other):
            return isinstance(other, WrappedVal) and type(self.val) == type(other.val) and self.val == other.val
        def __hash__(self):
            return hash((type(self.val), self.val))
        def __repr__(self):
            return repr(self.val)  # 让打印出来的结果更直观
    
    # 包装所有元素
    my_set = {
        WrappedVal("Python"), WrappedVal("Java"),
        WrappedVal(1), WrappedVal(0), WrappedVal(23.45),
        WrappedVal(True), WrappedVal(False)
    }
    print(my_set)
    # 输出示例:{0, 1, True, False, 'Python', 'Java', 23.45}
    

    这个方法的好处是,打印集合的时候看起来和普通元素差不多,使用的时候只需要访问.val属性就能拿到原始值。

  • 用元组存储值和类型
    更简单的办法是把每个值和它的类型组成一个元组,因为元组的哈希值会考虑所有元素,所以(1, int)和(True, bool)是完全不同的元组,集合会把它们都保留:

    my_set = {
        ("Python", str), ("Java", str),
        (1, int), (0, int), (23.45, float),
        (True, bool), (False, bool)
    }
    print(my_set)
    # 输出示例:{(0, <class 'int'>), (1, <class 'int'>), ('Python', <class 'str'>), (False, <class 'bool'>), ('Java', <class 'str'>), (True, <class 'bool'>), (23.45, <class 'float'>)}
    

    这个方法不用写类,非常直接,就是后续要使用原始值的时候,需要取元组的第一个元素,比如for item in my_set: print(item[0])。

顺带说下原理:为什么原来的集合会自动去重?因为集合判断两个元素是否重复的逻辑是:先比较它们的哈希值,如果哈希值相同,再用==判断是否相等。而hash(1) == hash(True),且1 == True,所以它们会被当成同一个元素,0和False也是同样的道理。

备注:内容来源于stack exchange,提问作者Venkata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:03:08