当前位置: 首页 > article >正文

别再被‘NoneType‘坑了!Python新手必看的5个实战避坑技巧(附代码)

别再被NoneType坑了Python新手必看的5个实战避坑技巧附代码刚学会用Python写爬虫的小张兴奋地运行了自己写的第一个爬虫脚本结果屏幕上赫然出现了一行刺眼的错误提示TypeError: NoneType object is not subscriptable。他盯着这行错误信息发了半天呆完全不明白为什么一个简单的列表访问会引发这样的错误。这可能是每个Python初学者都会遇到的经典场景——当你以为掌握了基础语法准备大展拳脚时None这个看似简单的概念却给了你当头一棒。None在Python中代表无或空值但它不是0不是False也不是空列表或空字符串——它是一个独立的数据类型NoneType。新手最容易犯的错误就是把None当成其他空值来处理结果在尝试访问属性或元素时遭遇TypeError。这种错误特别容易出现在处理API返回、数据库查询结果和函数返回值时因为这些场景中None经常作为无结果的标志出现。1. 为什么None会成为Python新手的噩梦None引发的错误之所以让新手头疼主要有三个原因静默失败很多函数在找不到结果时会返回None而不会抛出异常这导致错误可能在代码中传播很远才被发现错误信息不直观TypeError: NoneType object is not subscriptable这样的提示对新手来说不够友好与空容器的混淆新手常常分不清None和[]、等空容器的区别看看这个典型的爬虫代码片段import requests def get_page_title(url): response requests.get(url) if response.status_code 200: return response.text.split(title)[1].split(/title)[0] title get_page_title(https://example.com) print(title.upper())这段代码看似合理但实际上隐藏着两个潜在的NoneType陷阱如果请求失败如网络问题response可能是None即使请求成功如果页面没有title标签split()操作会引发IndexError2. 防御性编程5个实战避坑技巧2.1 明确检查None的时机和方式最直接的解决方案是在访问对象前检查它是否为None但关键在于何时检查和如何检查。推荐做法result some_function_that_may_return_none() # 不好的写法过度检查 if result is not None and len(result) 0 and result ! : ... # 好的写法根据上下文合理检查 if result is None: # 处理None情况 return # 如果是容器类型再检查是否为空 if not result: # 会捕获None、[]、、{}等所有假值 ...何时使用is Nonevs None总是使用is None因为is比较对象标识而非值可能被重载行为不可预测2.2 使用空容器替代None在很多情况下我们可以用空列表[]、空字典{}或空字符串代替None这样可以避免NoneType错误同时保持代码简洁。数据库查询示例# 不推荐返回None表示无结果 def get_user_by_id(user_id): user db.query(SELECT * FROM users WHERE id ?, user_id) return user[0] if user else None # 推荐返回空字典表示无结果 def get_user_by_id(user_id): user db.query(SELECT * FROM users WHERE id ?, user_id) return user[0] if user else {}这样调用方可以安全地访问属性而不用担心NoneType错误user get_user_by_id(123) print(user.get(name, Anonymous))2.3 合理的默认值和or运算符的妙用Python的or运算符有一个有用的特性它返回第一个为真的操作数否则返回最后一个操作数。这可以用来提供默认值。API响应处理示例api_response get_api_response() or {} # 如果api_response是None则使用{} data api_response.get(data, [])注意这种方法只适用于None和假值如、[]、0等可以互换的情况。如果需要严格区分None和其他假值应该使用显式检查。2.4 异常处理的正确姿势虽然try/except可以捕获NoneType错误但滥用异常处理会导致代码难以维护。应该遵循以下原则只捕获你预期会发生的异常不要用裸except:捕获所有异常在合适的抽象层级处理异常通常在函数边界处理提供有意义的错误信息帮助调试改进后的爬虫示例def get_page_title(url): try: response requests.get(url, timeout5) response.raise_for_status() # 如果状态码不是200抛出HTTPError content response.text title content.split(title)[1].split(/title)[0] return title.strip() if title else None except (requests.RequestException, IndexError) as e: logging.warning(fFailed to get title from {url}: {str(e)}) return None title get_page_title(https://example.com) if title is None: title Default Title2.5 类型注解和静态检查Python 3.5支持类型注解配合mypy等静态检查工具可以在运行前发现潜在的NoneType问题。from typing import Optional, List def get_user_names() - Optional[List[str]]: 返回用户名列表如果查询失败则返回None ... users get_user_names() # mypy会警告users可能是None print(users[0])修复方案users get_user_names() if users is None: users [] print(users[0] if users else No users)3. 真实项目中的None处理模式在实际项目中None处理往往更加复杂。以下是几种常见场景的处理策略3.1 链式调用中的None处理处理深层嵌套数据结构时传统的None检查会导致代码嵌套过深if data is not None: if data.get(user) is not None: if data[user].get(profile) is not None: name data[user][profile].get(name)Python 3.8引入了:运算符可以简化这种检查if (data is not None and (user : data.get(user)) is not None and (profile : user.get(profile)) is not None and (name : profile.get(name)) is not None): ...或者使用第三方库如pydash的get函数from pydash import get name get(data, user.profile.name, defaultUnknown)3.2 ORM和数据库交互中的None在使用SQLAlchemy等ORM时None有特殊含义class User(db.Model): id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(80), nullableFalse) # 不允许NULL bio db.Column(db.Text, nullableTrue) # 允许NULL # 查询可能返回None user User.query.get(123) # 如果id123的用户不存在返回None # 解决方案1使用first()替代get() user User.query.filter_by(id123).first() or default_user # 解决方案2使用get_or_404在Web应用中常用 from flask_sqlalchemy import abort user User.query.get(123) or abort(404)3.3 缓存中的None陷阱使用缓存时None可能表示两种不同情况缓存未命中键不存在缓存命中但值为Nonedef get_user_from_cache(user_id): # 不推荐无法区分无缓存和缓存了None return cache.get(user_id) # 推荐使用哨兵对象区分两种情况 MISSING object() def get_user_from_cache(user_id): user cache.get(user_id, MISSING) if user is MISSING: # 从数据库加载 user db.get_user(user_id) cache.set(user_id, user) return user4. 高级技巧自定义None安全访问工具对于大型项目可以创建None安全的访问工具函数def safe_get(d, *keys, defaultNone): 安全获取嵌套字典的值 for key in keys: try: d d[key] except (TypeError, KeyError, AttributeError): return default return d # 使用示例 data {user: {profile: {name: Alice}}} name safe_get(data, user, profile, name, defaultUnknown)或者创建一个None安全的属性访问装饰器def none_safe(func): 装饰器如果第一个参数是None返回None而不调用函数 functools.wraps(func) def wrapper(obj, *args, **kwargs): return None if obj is None else func(obj, *args, **kwargs) return wrapper # 使用示例 none_safe def get_length(x): return len(x) get_length([1,2,3]) # 3 get_length(None) # None5. 测试中的None处理良好的测试应该覆盖None相关的边界条件import pytest def test_get_page_title(): # 测试正常情况 assert get_page_title(titleHello/title) Hello # 测试无title标签的情况 assert get_page_title(html/html) is None # 测试None输入 with pytest.raises(TypeError): get_page_title(None) # 测试空字符串 assert get_page_title() is None使用pytest的参数化测试可以更简洁地测试多种情况pytest.mark.parametrize(input,expected, [ (titleHi/title, Hi), (html/html, None), (, None), (None, pytest.raises(TypeError)), ]) def test_get_page_title(input, expected): if isinstance(expected, type) and issubclass(expected, Exception): with expected: get_page_title(input) else: assert get_page_title(input) expected

相关文章:

别再被‘NoneType‘坑了!Python新手必看的5个实战避坑技巧(附代码)

别再被NoneType坑了!Python新手必看的5个实战避坑技巧(附代码) 刚学会用Python写爬虫的小张,兴奋地运行了自己写的第一个爬虫脚本,结果屏幕上赫然出现了一行刺眼的错误提示:TypeError: NoneType object is …...

如何用 expires 和 max-age 属性控制 cookie 的生命周期

Max-Age 优先级高于 Expires,覆盖其设置;Expires 依赖客户端时间且需 GMT 格式,省略则为会话 Cookie;Max-Age 以秒为单位、不依赖本地时间,值为 0 或负数时立即删除。Cookie 的生命周期由 Expires 和 Max-Age 两个属性…...

c++怎么抛出文件读写异常_exceptions()方法开启流异常【详解】

需调用exceptions()设置failbit和badbit掩码,构造后立即设置并显式open()才能自动抛异常;若流已失败则调用exceptions()会立即抛出ios_base::failure。std::ifstream/ofstream 怎么自动抛异常而不是静默失败默认情况下,C 的 std::ifstream 和…...

将 realme 联系人导出到 Excel 的 4 种方法

升级手机后,担心丢失Android联系人?别担心。换新手机时,强烈建议将Android联系人导出到 Excel。Excel 可以更轻松地整理、备份和在设备之间迁移联系人。但将Android联系人导出到 Excel 并不总是那么简单。如果您是 realme 用户并想知道如何将…...

小龙虾的自我养成之路

我为什么会发出这个疑问呢?是因为我研究Web开发中的一个问题时,请求体在 Filter(过滤器)处被读取了之后,在 Controller(控制层)就读不到值了,使用 RequestBody 的时候。 无论是字节流…...

免费3D重建神器Meshroom完全指南:从照片到专业模型的终极教程

免费3D重建神器Meshroom完全指南:从照片到专业模型的终极教程 【免费下载链接】Meshroom Node-based Visual Programming Toolbox 项目地址: https://gitcode.com/gh_mirrors/me/Meshroom 你是否梦想过将手机拍摄的普通照片变成逼真的3D模型?现在…...

智慧树自动刷课插件终极教程:3步实现高效学习自动化 [特殊字符]

智慧树自动刷课插件终极教程:3步实现高效学习自动化 🚀 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 还在为智慧树平台的繁琐操作而烦恼吗&am…...

VoxelNet论文精读与复现笔记:从体素划分到RPN,一步步拆解3D检测核心

VoxelNet论文精读与复现笔记:从体素划分到RPN,一步步拆解3D检测核心 在自动驾驶和机器人感知领域,3D目标检测一直是核心技术难题。传统方法依赖手工设计特征,而VoxelNet首次实现了从原始点云到3D边界框的端到端学习。本文将带您深…...

从map到base_link:深入解析ROS激光SLAM中的坐标变换链与数据流

1. 激光SLAM中的坐标系基础认知 第一次接触ROS激光SLAM时,我被各种坐标系搞得晕头转向。直到有次调试机器人导航时,发现地图总是偏移,才真正意识到坐标系理解的重要性。在激光SLAM系统中,数据就像接力赛跑,需要经过多个…...

Late:本地优先的编程智能体

如果能在 5GB 显存上使用本地 Qwen3.5-35B-A3B 编排代码库(通过 llama.cpp 达到约 25-30 tokens/sec,65k 上下文,其余层卸载到系统内存),你觉得如何? 更妙的是,两个并行的 agent 实例可以舒适地…...

高效使用NotebookLM的5种方法

如果你曾经被笔记、PDF、研究论文,甚至自己的想法弄得焦头烂额,那么谷歌的 NotebookLM 很可能会成为你最喜欢的新工具。 你可以把它想象成一个智能研究助手,它不仅真正理解你的文档,还能帮助你更好地思考,而不仅仅是更…...

Qianfan-OCR效果分享:培训教材PPT→知识点分级+案例引用+习题答案结构化

Qianfan-OCR效果分享:培训教材PPT→知识点分级案例引用习题答案结构化 1. 工具概览 Qianfan-OCR是基于百度千帆InternVL架构开发的单卡GPU专属文档解析工具,专为解决教育培训场景中的复杂文档解析需求而设计。与传统OCR工具不同,它不仅能识…...

使用FCM进行编码解码

文章目录1 FCM到底是什么?2 为什么论文里要用FCM?3 FCM输出的两个核心结果是什么?1. prototype / cluster centers2. membership matrix4 FCM到底在优化什么?5 FCM是怎么一步一步算出来的?第一步:先定簇数 c第二步:初始化隶属度矩阵第三步&#xff…...

TuShare的注册和使用

前言 TuShare是比较知名的证券第三方数据提供网站,最近我被试用各种爬虫搞烦了。打算花点钱直接试用第三方的数据看看。 1、TuShare上账号的注册 打开TuShare网址 https://tushare.pro/2、安装Tushare对应的包 Pip install tushare如果安装途中有断开的话&#xff0…...

在PyCharm的Django工程中修改初始页

1、原始的初始页2、setting.py中添加应用在quiz_site的setting.py 进行应用到的设置(对应的是一个根目录下的文件夹)3、Quiz_site\urls.py中的设置4、修改quiz/urls.py修改后的内容如下:5、views.py的设置如图:6、建立主页在quiz目…...

全栈编程基础知识8

全栈编程基础知识81.Redis1.介绍:基于C语言。开发的一款nosql数据库,基于内存的,读写快,支持多种数据类型。存的是键值对。2.类型:string list hash set bitmap,sorted set等。支持事务,lua脚本…...

大模型RAG (三)

一、文档的加载和分割1、文档LLM回复系统搭建2、把文本切分成chunks把文本切分成chunks的方式有很多种: 1.按照句子来切分 2.按照字符数来切分 3.按固定字符数结合overlapping window 4. 递归方法 RecursiveCharacterTextSplitter案例1: 按照句子来切分import retxt…...

航空特色学校建设实施方案

【核心亮点】1. "三维一体"课程体系:● 基础课(航空原理/飞行启蒙) 专项课(模拟飞行、航模制作、无人机编程) 学科融合课(航空物理/美术/编程),覆盖全学段。● 自主研发校…...

学工平台变革之旅:从管理到成长赋能,真正为学生点亮前行之路

✅作者简介:合肥自友科技 📌核心产品:智慧校园平台(包括教工管理、学工管理、教务管理、考务管理、后勤管理、德育管理、资产管理、公寓管理、实习管理、就业管理、离校管理、科研平台、档案管理、学生平台等26个子平台) 。公司所有人员均有多…...

智慧校园的权限管控,如何按角色精准设置操作范围?

✅作者简介:合肥自友科技 📌核心产品:智慧校园平台(包括教工管理、学工管理、教务管理、考务管理、后勤管理、德育管理、资产管理、公寓管理、实习管理、就业管理、离校管理、科研平台、档案管理、学生平台等26个子平台) 。公司所有人员均有多…...

Java 25虚拟线程性能断崖式跃迁:阿里云真实订单链路压测数据(RT从412ms→23ms,附全链路火焰图)

第一章:Java 25虚拟线程演进脉络与高并发架构新范式Java 25正式将虚拟线程(Virtual Threads)从预览特性转为标准特性,标志着JVM并发模型进入“轻量级线程即原语”时代。这一转变并非孤立演进,而是历经Project Loom多年…...

【毕设】城镇保障性住房管理系统

💟博主:程序员俊星:CSDN作者、博客专家、全栈领域优质创作者 💟专注于计算机毕业设计,大数据、深度学习、Java、小程序、python、安卓等技术领域 📲文章末尾获取源码数据库 🌈还有大家在毕设选题…...

【毕设】城市公园信息管理系统的设计与实现

💟博主:程序员俊星:CSDN作者、博客专家、全栈领域优质创作者 💟专注于计算机毕业设计,大数据、深度学习、Java、小程序、python、安卓等技术领域 📲文章末尾获取源码数据库 🌈还有大家在毕设选题…...

从dbus-send到busctl:手把手教你迁移到更现代的D-Bus调试工具链

从dbus-send到busctl:现代D-Bus调试工具链迁移实战指南 如果你曾经在Linux系统中与D-Bus打交道,那么对dbus-send这个老牌命令行工具一定不陌生。它就像一把瑞士军刀,虽然功能全面但用起来总有些笨拙——复杂的参数构造、晦涩的输出格式、缺乏…...

DevExpress GridControl单元格合并后无法编辑?一个属性帮你避开这个坑

DevExpress GridControl单元格合并实战:解决编辑冲突与高级应用 当我们在企业级应用开发中使用DevExpress的GridControl时,单元格合并是一个常见的可视化需求。想象一下这样的场景:你的财务系统需要展示客户交易记录,而同一个客户…...

别再只会用Canny了!深入对比Sobel、Prewitt、LoG:OpenCV边缘检测算法选型与避坑指南

边缘检测算法深度解析:从Sobel到Canny的工程实践指南 在计算机视觉领域,边缘检测是图像处理中最基础也最关键的步骤之一。许多开发者习惯性地将Canny算子作为默认选择,却忽略了其他算法在不同场景下的独特优势。本文将带您深入理解主流边缘检…...

我的模型总在测试集翻车?可能是数据增强的‘姿势’不对!聊聊那些年我们踩过的坑

模型测试集翻车?数据增强的六大陷阱与实战解决方案 当你满怀期待地将精心调参的模型投入测试集,却发现性能断崖式下跌——这种挫败感每个算法工程师都深有体会。上周团队里一位资深研究员盯着0.23的测试F1分数苦笑:"训练集明明98%准确率…...

MATLAB优化实战:从fminsearch到fmincon的工程问题求解

1. MATLAB优化工具箱入门:从实际问题到数学模型 第一次接触MATLAB优化工具箱时,我被它强大的功能震撼到了。记得当时正在做一个机械臂参数标定的项目,需要根据实验数据反推关节参数。这个问题本质上就是个典型的无约束优化问题,正…...

**链路追踪实战:用Go语言打造分布式系统的“心跳图谱”**在微服务架构日益普及的今天,一

链路追踪实战:用Go语言打造分布式系统的“心跳图谱” 在微服务架构日益普及的今天,一个请求可能跨越多个服务、几十个中间件甚至上百个节点。当问题出现时,传统的日志排查方式早已力不从心。这时,链路追踪(Tracing&am…...

第三章 低通滤波(LPF)

一 应用场景及公式当负载设备VCC需要的电压是1V,但是我们有12V的电压时,就需要使用电阻分压。问题:非理想环境中12V的电压会有波动(噪声)的,故而分出来1V电压也是有噪声的。1.1 容抗公式 :容抗&#xff08…...