0

0

Python 中 in 运算符在集合和列表中的不同行为

心靈之曲

心靈之曲

发布时间:2025-09-25 17:09:21

|

469人浏览过

|

来源于php中文网

原创

python 中 in 运算符在集合和列表中的不同行为

Python 中 in 运算符在集合和列表中的不同行为

本文深入探讨了 Python 中 in 运算符在集合(set)和列表(list)中的不同行为。通过分析其内部实现机制,解释了为何在特定情况下,使用 in 运算符在列表中会引发错误,而在集合中却能正常运行。此外,还提供了自定义类和 Pytorch 张量的示例,以帮助读者更好地理解和应用 in 运算符,并针对 Pytorch 张量比较问题,提供了一种基于张量大小的解决方案。

在 Python 中,in 运算符用于检查某个元素是否存在于一个集合中。然而,其行为在不同类型的集合(如列表和集合)中有所不同。理解这些差异对于编写高效且健壮的代码至关重要。

in 运算符的工作原理

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

1. 不使用哈希表的集合(列表、元组等)

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

当 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),如果身份不同,则进行相等性比较 (==)。
  • 只要找到第一个匹配项,就返回 True。

2. 使用哈希表的集合(集合、字典等)

当 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 相同的元素子集 subset。这是集合查找速度快的原因。
  • 然后,迭代 subset 中的每个元素 c,进行身份比较和相等性比较,并在找到第一个匹配项时停止。即使对于非常大的数据集,subset 通常也只有 1 个或几个元素。
  • 注意:集合中元素的哈希值在添加到集合时计算,而 x 的哈希值在使用 in 运算符时计算。

示例:自定义类

为了更好地理解 in 运算符的行为,我们可以创建一个自定义类 MyObj,并定义其自己的哈希计算逻辑 (hash(x)) 和相等性逻辑 (x == c):

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=}")
        return super().__eq__(other)

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

然后,创建几个 MyObj 实例,并创建一个集合 s 和一个列表 lst:

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__。

1. 集合中的 in 运算符

Python精要参考 pdf版
Python精要参考 pdf版

这本书给出了一份关于python这门优美语言的精要的参考。作者通过一个完整而清晰的入门指引将你带入python的乐园,随后在语法、类型和对象、运算符与表达式、控制流函数与函数编程、类及面向对象编程、模块和包、输入输出、执行环境等多方面给出了详尽的讲解。如果你想加入 python的世界,David M beazley的这本书可不要错过哦。 (封面是最新英文版的,中文版貌似只译到第二版)

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

Python 首先计算 x 的哈希值。如果存在哈希冲突,Python 还需要调用 __eq__,因此也会调用 x == c。

2. 列表中的 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,如果结果为 True(身份检查),则不需要检查 x == c 的相等性。如果身份检查结果为 False,则 Python 会检查 x == c 的相等性。

Pytorch 张量中的注意事项

在 Pytorch 中,如果尝试比较大小不同的张量 a 和 b,则会引发 RuntimeError。torch.Tensor 的哈希值计算只是返回 id(self)。

当执行 b in list([a, b]) 时,会引发错误,因为逻辑会比较:

  • id(b) is id(a) -> False
  • b == a -> 引发 RuntimeError,因此永远不会将 b 与列表中的 b 进行比较。

当执行 b in set([a, a, b]) 时,不会引发错误,因为集合会转换为类似于 s = {id(a): a, id(b): b} 的哈希表。b in s 执行以下操作:

  • "hash(b) 是否与 s 的哈希表中的任何哈希值相同?是的!"
  • b is b?(in 左侧的 b 是否与集合中哈希值与 b 相同的对象相同?)。这是 True。

总结:b in set([a, b]) 和 b in [a, b] 之间的区别在于,对于列表,将按顺序检查 (x is c or x==c),而对于集合,将首先检查哈希值,然后迭代集合中具有相同哈希值的所有项以检查 (x is c or x==c)。由于 hash(b) != hash(a),几乎永远不会比较 b == a,从而在大多数情况下避免了 RuntimeError。

解决方案

为了解决 Pytorch 张量比较的问题,可以利用 torch.Tensor.size 属性(它是元组的子类),并创建一个集合(或列表)字典,用于存储不同大小的张量。

例如:

import torch

tensors_by_size = {}

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

def add_tensor(tensor):
    size = tuple(tensor.size())
    if size not in tensors_by_size:
        tensors_by_size[size] = set()
    tensors_by_size[size].add(tensor)

add_tensor(a)
add_tensor(b)
add_tensor(c)

def check_tensor(tensor):
    size = tuple(tensor.size())
    return size in tensors_by_size and tensor in tensors_by_size[size]

print(check_tensor(a)) # True
print(check_tensor(torch.Tensor(2,3))) # False 因为是新的tensor对象
print(check_tensor(b)) # True

通过这种方式,可以避免直接比较大小不同的张量,从而避免 RuntimeError。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1500

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

231

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1500

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

231

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

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

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

22

2026.01.27

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新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号