别再死记 self 和 cls!Python 类方法底层逻辑一次性讲透
2026/8/9 12:11:58 网站建设 项目流程

🚨 重要提醒

很多初学 Python 的小伙伴,写面向对象代码时,都有一个刻板印象:实例方法第一个参数必须是 self,类方法必须是 cls。一旦改个名字、少写一个参数,代码直接爆红报错,让人一头雾水。

其实根本不用死记硬背!self、cls 只是程序员的约定俗成,压根不是 Python 关键字。今天咱们抛开刻板规则,用最通俗的大白话,拆解实例方法、自定义参数、报错根源、类方法的全部核心逻辑。

一、颠覆认知:实例方法的 self 可以随便改名

首先纠正所有人的误区:self 不是固定语法,只是一个普通形参变量名。

1. 常规写法(人人都会)

我们最熟悉的 self 写法,本质就是接收自动传入的实例对象:

class MathTool: # self 接收自动传入的实例对象 def add(self, a, b): return a + b 创建实例对象 obj = MathTool() 调用时,Python自动把 obj 传给 self,10、20 分别传给 a、b print(obj.add(10, 20)) # 输出 30

2. 魔改写法(合法且正常运行)

咱们直接把 self 改成 abc,代码一点毛病没有,运行结果完全一致:

class MathTool: # 把 self 换成任意变量名都行 def add(abc, a, b): return a + b obj = MathTool() 依旧正常输出30 print(obj.add(10, 20)) # 输出 30

这里的 abc 和平时的 self 完全等价,都是代表当前调用方法的实例对象。

那为什么全网都默认用 self?单纯是行业编码规范,统一命名可读性更高,仅此而已,没有任何语法强制约束。

二、高频报错深度解析:少写 self 为什么会报错?

很多人踩过这个坑:写实例方法时,偷懒不写第一个参数,直接定义两个形参,调用就直接爆红:

TypeError: add() takes 2 positional arguments but 3 were given

咱们用大白话拆解报错根源,看完永远不会再错!

错误代码演示

# 错误写法:省略了实例方法的第一个占位参数 class MathTool: def add(a, b): return a + b obj = MathTool() 调用报错! print(obj.add(10, 20))

报错底层逻辑(核心重点)

  1. 实例方法的固定机制:只要是对象调用实例方法,Python 强制自动传入 1 个参数(实例对象本身),这个是底层机制,无法跳过;
  2. 参数数量冲突:我们定义的 add(a,b) 只接收2个形参,但调用时实际传入了 obj、10、20 一共3个实参;
  3. 最终结果:形参装不下实参,直接触发参数数量不匹配报错。

简单总结:实例方法的第一个参数,是专门用来「接住自动传入的实例对象」的占位符,绝对不能省略。

三、进阶升级:类方法 @classmethod 全解析

搞懂了实例方法的 self 逻辑,类方法的 cls 就一通百通了!它和实例方法逻辑相似,但作用完全不同。

1. 类方法核心规则

  • 必须加装饰器@classmethod标记;
  • 第一个参数默认约定为 cls(同样不是关键字,可改名),代表类本身,而非实例对象;
  • 调用方式灵活:既可以用类名调用,也可以用实例对象调用。

2. 类方法代码示例

class MathTool: # 定义类方法 @classmethod def show_info(cls): # cls 代表当前类 MathTool print(f"当前类名:{cls.__name__}") 1. 类名直接调用(推荐写法) MathTool.show_info() # 当前类名:MathTool 2. 实例对象调用(合法但不推荐) obj = MathTool() obj.show_info() # 当前类名:MathTool

3. 类方法的权限边界(高频考点)

很多人分不清类方法和实例方法的使用场景,记住这一组核心区别即可:

  • 可读可写类属性:cls 指向类本身,所以可以直接操作类的公共属性、修改类全局数据;
  • 无法直接访问实例属性:类方法没有 self 参数,不绑定具体实例对象,不能直接调用实例独有的属性和方法;
  • 无实例绑定:类方法属于类,不属于某个具体对象,所有对象共享同一个类方法。

四、终极总结(懒人速记版)

  1. 实例方法 self:非关键字、可自定义命名,接收实例对象,必须占位,用于操作实例属性;
  2. 参数报错根源:对象调用实例方法必自动传1个实例参数,少写占位参数必然参数溢出报错;
  3. 类方法 cls:非关键字、可自定义,接收类本身,需@classmethod装饰,操作类属性、不访问实例属性;
  4. 命名规范:self、cls 只是行业通用约定,为了代码统一易懂,生产环境禁止随意改名。

写在最后

Python 面向对象的语法从来不是死板的条条框框,所有看似“固定”的规则,底层都有清晰的运行逻辑。不用死记硬背,搞懂谁调用、传什么参数、参数给谁接,就能彻底搞定 self 和 cls,再也不会踩坑!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询