Python中的self用法详解
前言self大概是 Python 初学者最先记住、又最先误解的东西。它的误解通常集中在三点以为self是关键字以为它必须叫self以为「方法里的self会自动变成一个实例」。真相要从描述符协议说起函数本身就是一种非数据描述符non-data descriptor它被定义在类里之后通过实例做点号访问时会自动返回一个「绑定方法bound method」把实例塞到第一个参数的位置上。你写下的self本质上只是那个被塞进来的第一个形参的名字。官方文档写得很直白按惯例实例参数叫self但它叫this或任何别的名字都可以。所以这是一条「约定」不是语法。本文专讲self它到底是什么、为什么必须是第一个参数、staticmethod/classmethod与实例方法三者的差别、以及cls与self的区别。代码按 Python 3.8 给出。一、self 只是一个形参名先看一段故意「不守规矩」的代码证明self不是关键字# 适用于 Python 3.8class Point:def __init__(this, x, y): # 形参名故意叫 thisthis.x xthis.y ydef norm(self): # 这个方法里叫 selfreturn (self.x ** 2 self.y ** 2) ** 0.5p Point(3, 4)print(p.norm()) # 推演输出5.0print(Point.norm(p)) # 推演输出5.0两个方法一个用this、一个用self程序照跑不误。因为this和self只是位置上的第一个形参名字本身没有任何魔法。真正有魔法的是「点号访问 函数描述符」这套机制# 适用于 Python 3.8p Point(3, 4)print(p.norm) # 推演输出bound method Point.norm of ...print(p.norm.__self__ is p) # 推演输出Trueprint(p.norm.__func__ is Point.__dict__[norm]) # 推演输出Truep.norm拿到的不是原函数而是一个绑定方法对象。它内部记着两样东西原始函数__func__以及被绑定的实例__self__。调用p.norm()时CPython 实际执行的是Point.norm(p)——实例被自动塞到第一个参数的位置这就是self的全部来源。二、为什么必须是第一个参数因为绑定机制永远是「把实例放到参数列表的最前面」没有例外。你写def norm(self)接收的就是这个被塞进来的实例你写成def norm(a, b)那么a拿到实例、b只能等调用者再传一个参数。于是下面三条规则是强行成立的写法实际调用形式结果p.method()type(p).method(p)正常实例占据第一个参数Point.method(p)同上实例是显式传的正常两种写法完全等价Point.method()少了实例这个参数TypeError参数个数不足再对照官方的绑定规则表三种方法在「从实例调用」和「从类调用」时的变换一目了然方法种类从实例obj.f(*args)调用从类Cls.f(*args)调用普通函数实例方法f(obj, *args)f(*args)staticmethodf(*args)f(*args)classmethodf(type(obj), *args)f(cls, *args)注意第二、三列普通函数从类调用时不再自动补参数。这就是「Point.method()会报参数不足」的原因——走类调用时没人给你补实例。三、实例方法、类方法、静态方法三兄弟对比# 适用于 Python 3.8class Temperature:unit Cdef __init__(self, value):self.value valuedef show(self): # 实例方法第一个参数是实例return f{self.value}{self.unit}classmethoddef from_fahrenheit(cls, f): # 类方法第一个参数是类return cls((f - 32) * 5 / 9)classmethoddef set_unit(cls, u):cls.unit ustaticmethoddef is_valid(v): # 静态方法不接收任何隐式参数return -273.15 vt Temperature.from_fahrenheit(212)print(t.show()) # 推演输出100.0Cprint(Temperature.is_valid(-300)) # 推演输出Falseprint(t.is_valid(20)) # 推演输出True三个要点实例方法用self因为它要读 / 写实例自己的数据这里是self.value。类方法用cls因为它操作的是类一级的数据这里改了cls.unit或者要做「备用构造器」from_fahrenheit返回一个新实例。静态方法其实就是「放在类命名空间里的普通函数」。它不接收self也不接收cls。官方建议是当你有个函数在概念上属于这个类、但不需要访问实例或类的数据时用staticmethod。如果它连类的概念都不需要那它更适合当一个模块级函数。注意Temperature.unit C是类变量所以set_unit改它会让所有实例都跟着变这也正是类方法存在的价值。四、cls 与 self 的区别一句话self是「一个实例」cls是「一个类」。它们的名字同样是约定同样只是「绑定进来的第一个参数」——只不过classmethod绑定进来的是类而不是实例。关键差别在继承时的表现# 适用于 Python 3.8class Plugin:classmethoddef create(cls):return cls() # cls 是「实际被调用的那个类」staticmethoddef describe():return Plugin 的说明class AudioPlugin(Plugin):passprint(type(AudioPlugin.create()).__name__) # 推演输出AudioPluginprint(type(Plugin.create()).__name__) # 推演输出Pluginprint(AudioPlugin.describe()) # 推演输出Plugin 的说明AudioPlugin.create()里cls拿到的是AudioPlugin而不是Plugin所以造出来的是AudioPlugin实例。这就是「备用构造器」为什么一定要用cls而不是写死类名——写死类名的话子类调用时会造出父类的实例。而describe是静态方法它不知道调用者是谁AudioPlugin.describe()与Plugin.describe()返回同一个字符串。静态方法里没有cls也没有self这一点要和类方法严格区分开。常见坑点1. 定义实例方法时忘写self。❌def show():然后里面用self.value调用时报NameError或参数不匹配。 ✅def show(self):第一个参数永远留给实例。2. 把self当成关键字不敢改名。❌ 以为写def __init__(this, x)会报语法错误。 ✅self只是惯例名换成任何合法标识符都能跑但为了可读性团队里应统一用self。3. 在静态方法里使用self。❌staticmethod修饰的方法里写self.x报NameError。 ✅ 静态方法不接收隐式参数需要数据就通过参数显式传入或改用实例方法。4. 通过类名调用实例方法却忘了传实例。❌Point.norm()报TypeError: norm() missing 1 required positional argument。 ✅ 要么p.norm()要么Point.norm(p)把实例显式补上。5. 在类方法里写死类名而不是用cls。❌classmethod里写return Base()子类调用时造出的是父类实例。 ✅ 写return cls()让它跟随实际调用的类。6. 在__init__里把属性名拼错之后才报错。❌self.vlaue value然后在show()里访问self.value构造时不报错、用的时候才AttributeError。 ✅ 赋值和读取用同一个拼写__slots__能帮你在赋值阶段就把不存在的属性名挡下来。7. 以为self会自动创建实例属性。❌ 方法里只写了self.total 1没赋值期待属性凭空出现。 ✅ 实例属性是靠self.名字 值这个赋值动作创建的只读不写不会创建任何东西。总结概念是什么由谁绑定典型用途self第一个形参按约定叫self实例方法自动把实例传进来读写实例自己的数据cls第一个形参按约定叫cls类方法自动把类传进来备用构造器、改类级数据staticmethod不接收隐式参数的普通函数什么都不绑定与类概念相关但不依赖实例 / 类数据绑定方法对象函数 实例的组合函数描述符在点号访问时生成让p.m()等价于Cls.m(p)一句话收尾self不是关键字而是「绑定进来的第一个参数」的惯例名记住函数描述符与绑定方法这条链路实例方法、类方法、静态方法三种形式就都能一眼看穿。

相关新闻

Python中的super().__init__()用法详解

Python中的super().__init__()用法详解

前言 写子类时,很多人会习惯性地在 __init__ 里加一句 super().__init__(),问为什么,答「网上都这么写」。这句到底在做什么、什么时候会出错、多重继承下为什么顺序和你以为的不一样,往往说不清楚。 先纠正一个流传极广的说法&am…

2026/10/13 7:21:43 阅读更多 →
深度学习YOLOv8工地检测裸土是否覆盖数据集 建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测,智慧化建筑工地

深度学习YOLOv8工地检测裸土是否覆盖数据集 建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测,智慧化建筑工地

使用深度学习YOLOv8训练用于工地检测裸土是否覆盖数据集模型 ,通过训练建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测 文章目录使用深度学习YOLOv8训练用于工地检测裸土是否覆盖数据集模型 ,通过训练建筑工地裸土未覆盖检测数据集 识别判定裸土覆…

2026/10/12 20:43:22 阅读更多 →
pstack-claude:进程栈跟踪驱动的AI编程辅助工具

pstack-claude:进程栈跟踪驱动的AI编程辅助工具

1. 项目概述:pstack-claude 是什么,它解决的是哪类开发者的真实痛点?“pstack-claude”这个名称乍看像一个工具组合词,但拆解后立刻能抓住核心脉络:pstack是 Linux 系统中用于快速抓取进程调用栈的轻量级诊断命令&…

2026/10/12 22:53:06 阅读更多 →

最新新闻

WebSQL数据泄露防线:导出管控与数字水印溯源实践

WebSQL数据泄露防线:导出管控与数字水印溯源实践

一个周末的凌晨,我收到了一份从外部渠道流转回来的疑似泄露数据文件:一张几百行的客户信息表,字段完整,格式规整。按照惯例,首先要做来源定位——是开发环境泄露的?还是某个运营同学的本地文件流出去的&…

2026/10/13 7:22:01 阅读更多 →
Maven Archetype实战:构建可维护、可追溯的项目脚手架

Maven Archetype实战:构建可维护、可追溯的项目脚手架

1. 为什么“新建项目”不该从零敲代码——原型模板不是锦上添花,而是工程效率的分水岭我带过三届某高校软件工程方向的实训项目,每届都有至少12个小组。第一年,我让所有学生“从空文件夹开始搭建Spring Boot项目”:手动建src/main…

2026/10/13 7:22:01 阅读更多 →
强力卸载删注册表:彻底清理残留的完整指南与避坑实践

强力卸载删注册表:彻底清理残留的完整指南与避坑实践

简介:这份资源面向需要彻底卸载顽固软件、清理注册表残留的Windows用户与系统维护人员,核心是UninstallTool工具及其配套组件,用于解决常规卸载不干净、恶意软件隐藏痕迹、注册表键值被保护而难以删除等问题。压缩包共11个文件,约…

2026/10/13 7:22:01 阅读更多 →
C++Builder中Indy10网络通信组件实战:安装配置、TCP粘包处理与SSL避坑指南

C++Builder中Indy10网络通信组件实战:安装配置、TCP粘包处理与SSL避坑指南

简介:Indy10组件是一套面向CBuilder开发者的网络通信控件库,适用于CBuilder 4至6、2006至2010以及XE至XE8等多个版本,能够帮助开发者快速实现TCP/IP、HTTP、FTP等网络功能,适合需要跨版本维护或迁移网络应用的中高级程序员。资源包…

2026/10/13 7:22:01 阅读更多 →
Spring Boot接入Elasticsearch实战:部署、索引建模与查询优化

Spring Boot接入Elasticsearch实战:部署、索引建模与查询优化

很多人在Spring Boot项目里接入Elasticsearch时,最容易卡住的不是写代码,而是卡在“到底该怎么启动一个能用的ES环境”和“索引结构该怎么设计”这两步。网上教程要么只讲单机部署、要么只贴CRUD代码,真正把部署、索引设计、客户端选型、查询…

2026/10/13 7:22:01 阅读更多 →
Clover_v5.0_r5122_X64黑苹果引导实战:从U盘制作到多系统配置

Clover_v5.0_r5122_X64黑苹果引导实战:从U盘制作到多系统配置

简介:Clover_v5.0_r5122_X64 是一款面向黑果(Hackintosh)爱好者的四叶草启动引导程序,专为64位体系结构设计,核心作用是模拟苹果原生启动管理器,让非苹果硬件也能识别并加载 macOS 内核,尤其适配…

2026/10/13 7:21:01 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →