0

0

Python中 in 操作符在集合与列表中的不同行为详解

聖光之護

聖光之護

发布时间:2025-09-25 17:36:01

|

1007人浏览过

|

来源于php中文网

原创

python中 in 操作符在集合与列表中的不同行为详解

本文深入探讨了 Python 中 in 操作符在集合 (set) 和列表 (list) 这两种数据结构中的不同行为。通过分析其内部实现机制,解释了为何在某些情况下,使用 in 操作符时,列表会引发错误,而集合却能正常运行。同时,结合 PyTorch 张量 (Tensor) 的特性,提供了针对特定问题的解决方案,并给出了 in 操作符使用的注意事项。

in 操作符的工作原理

x in collection 在 Python 中的行为取决于 collection 的类型。具体来说,使用内部哈希表的集合和字典与不使用哈希表的列表和元组的工作方式不同。

列表和元组 (不使用哈希表)

当 collection 是列表或元组时,x in collection 的内部实现类似于以下伪代码:

def is_in(x, collection):
  for c in collection:
      if (x is c or x == c):
          return True
  return False

此方法按顺序将 collection 中的每个元素 c 与 x 进行比较,直到找到第一个匹配项。首先比较身份 (is),如果身份不同,则比较相等性 (==)。

立即学习Python免费学习笔记(深入)”;

集合和字典 (使用哈希表)

当 collection 是集合或字典时,x in collection 的内部实现如下:

def is_in(x, collection):
  # 选择集合中哈希值与 x 相同的元素子集
  subset = get_subset_by_hash(collection, hash(x))
  for c in subset:
      if (x is c or x == c):
          return True
  return False

此方法首先从 collection 中选择哈希值与 x 匹配的元素子集。然后,它迭代该子集,并将每个元素 c 与 x 进行比较(首先比较身份,然后比较相等性),并在找到第一个匹配项时停止。哈希表的运用使得查找速度更快,尤其是在处理大型数据集时。

注意: 集合中元素的哈希值在元素添加到集合时计算,而 x 的哈希值在使用 in 操作符时计算。

示例:自定义类 MyObj

为了更清楚地理解 in 操作符的行为,我们可以创建一个自定义类 MyObj,并定义其自身的哈希计算逻辑 (__hash__) 和相等性比较逻辑 (__eq__):

PictoGraphic
PictoGraphic

AI驱动的矢量插图库和插图生成平台

下载
class MyObj:
    def __init__(self, val, hashval):
        self._val = val
        self._hashval = hashval

    def __hash__(self):
        print(f"{str(self)} calling __hash__")
        return self._hashval

    def __eq__(self, other):
        print(f"{str(self)} calling __eq__, other={other}")
        return self._val == other._val if isinstance(other, MyObj) else False

    def __repr__(self):
        return f"<{self.__class__.__name__}: {self._val}>"

创建 MyObj 类的实例,并将其添加到集合和列表中:

a = MyObj("a", 123)
b = MyObj("b", 456)
d = MyObj("d", 456)  # 与 b 具有相同的哈希值

print("Creating set `s`")
s = set([a, b, d])

print("Creating list `lst`")
lst = [a, b, d]

运行结果表明,创建集合时,Python 会计算元素的哈希值。如果存在哈希冲突(例如,b 和 d 具有相同的哈希值),则还需要调用 __eq__ 方法进行比较。

in 操作符与集合

>>> s
{, , }
>>> b in s
 calling __hash__
True
>>> d in s
 calling __hash__
 calling __eq__, other=
 calling __eq__, other=
True

使用 in 操作符时,Python 首先计算 x 的哈希值。如果存在哈希冲突,则还需要调用 __eq__ 方法。

in 操作符与列表

>>> lst
[, , ]
>>> a in lst
True
>>> b in lst
 calling __eq__, other=
 calling __eq__, other=
True
>>> d in lst
 calling __eq__, other=
 calling __eq__, other=
 calling __eq__, other=
 calling __eq__, other=
True

对于列表,Python 首先检查身份 (x is c)。如果身份相同,则不需要检查相等性 (x == c)。如果身份不同,则检查相等性。

PyTorch 张量的特殊情况

PyTorch 张量在进行相等性比较时,如果形状不一致,会引发 RuntimeError。这是导致原始问题中列表引发错误的原因。

import torch
a = torch.Tensor(2,3)
b = torch.Tensor(2)

# case 1a:
# b  in list([a,a,b]) # raises an error: 
# RuntimeError: The size of tensor a (2) must match the size of tensor b (3) at non-singleton dimension 0

# case 1b
b in set([a,a,b]) # True (i.e. no error)

在 b in list([a, b]) 中,由于 a 和 b 的形状不同,在进行 b == a 比较时会引发 RuntimeError。而在 b in set([a, b]) 中,由于集合首先进行哈希值比较,而 torch.Tensor 的哈希值是其内存地址,因此在绝大多数情况下 hash(a) 和 hash(b) 是不同的,从而避免了 b == a 的比较,避免了错误。

解决方案

一种解决方案是使用 torch.Tensor.size() 属性(它是元组的子类),并创建一个字典或集合,用于存储不同大小的张量。

import torch

tensors_by_size = {}
a = torch.Tensor(2, 3)
b = torch.Tensor(2)

size_a = tuple(a.size())
size_b = tuple(b.size())

if size_a not in tensors_by_size:
    tensors_by_size[size_a] = set()
tensors_by_size[size_a].add(a)

if size_b not in tensors_by_size:
    tensors_by_size[size_b] = set()
tensors_by_size[size_b].add(b)

# Now you can check if a tensor of a certain size exists
target_tensor = torch.Tensor(2)
target_size = tuple(target_tensor.size())

if target_size in tensors_by_size:
    print("Tensor of size", target_size, "exists.")
    if target_tensor in tensors_by_size[target_size]:
        print("Tensor exists in the collection")
    else:
        print("Tensor of that size exists, but not that specific tensor.")
else:
    print("Tensor of size", target_size, "does not exist.")

总结

in 操作符在 Python 中对于集合和列表的行为有所不同。理解其内部实现机制,可以帮助我们更好地利用这些数据结构,并避免潜在的错误。在处理 PyTorch 张量等特殊类型时,需要特别注意其相等性比较的规则,并采取相应的解决方案。使用哈希表可以优化查找速度,但在某些情况下,可能会掩盖潜在的错误。因此,在选择数据结构时,需要根据实际情况进行权衡。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

538

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

26

2026.01.06

pytorch是干嘛的
pytorch是干嘛的

pytorch是一个基于python的深度学习框架,提供以下主要功能:动态图计算,提供灵活性。强大的张量操作,实现高效处理。自动微分,简化梯度计算。预构建的神经网络模块,简化模型构建。各种优化器,用于性能优化。想了解更多pytorch的相关内容,可以阅读本专题下面的文章。

432

2024.05.29

Python AI机器学习PyTorch教程_Python怎么用PyTorch和TensorFlow做机器学习
Python AI机器学习PyTorch教程_Python怎么用PyTorch和TensorFlow做机器学习

PyTorch 是一种用于构建深度学习模型的功能完备框架,是一种通常用于图像识别和语言处理等应用程序的机器学习。 使用Python 编写,因此对于大多数机器学习开发者而言,学习和使用起来相对简单。 PyTorch 的独特之处在于,它完全支持GPU,并且使用反向模式自动微分技术,因此可以动态修改计算图形。

24

2025.12.22

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

167

2026.01.28

包子漫画在线官方入口大全
包子漫画在线官方入口大全

本合集汇总了包子漫画2026最新官方在线观看入口,涵盖备用域名、正版无广告链接及多端适配地址,助你畅享12700+高清漫画资源。阅读专题下面的文章了解更多详细内容。

35

2026.01.28

ao3中文版官网地址大全
ao3中文版官网地址大全

AO3最新中文版官网入口合集,汇总2026年主站及国内优化镜像链接,支持简体中文界面、无广告阅读与多设备同步。阅读专题下面的文章了解更多详细内容。

74

2026.01.28

php怎么写接口教程
php怎么写接口教程

本合集涵盖PHP接口开发基础、RESTful API设计、数据交互与安全处理等实用教程,助你快速掌握PHP接口编写技巧。阅读专题下面的文章了解更多详细内容。

2

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号