Python 中的 self
在实例方法里,第一个参数通常命名为 self,表示当前实例。调用 obj.method(...) 时,解释器会把 obj 自动作为第一个位置参数传给 method,因此方法定义里要留出这个形参,才能在方法体内访问实例属性和其它实例方法。
这与 Java、C++ 等语言里隐式的 this 不同:Python 把「当前对象」显式写在参数列表里(名字习惯叫 self,见下文)。
相关主题可结合 类与对象、构造函数 __init__、静态方法 阅读。
self 是关键字吗?
不是。 self 只是约定俗成的参数名,可以改成别的名字(不推荐)。若不用 self,代码可读性差,且与社区规范不一致。
基本示例
class Dog:
def __init__(self, breed):
self.breed = breed
def bark(self):
print(f"{self.breed} is barking.")
d = Dog("Labrador")
d.bark()输出:
Labrador is barking.说明:
__init__(self, breed)在构造实例时被调用;除self外你传入的实参对应后面的形参(这里只需传breed)。self由解释器绑定到新实例,不必在Dog(...)里手动传入。bark(self)通过d.bark()调用时,d会作为第一个参数传给self。- 访问实例字段用
self.breed等形式。
可以省略 self 吗?
若把实例方法写成没有第一个参数的普通函数,通过实例调用会报错:解释器仍会传入「当前实例」这一实参。
class Dog:
def bark():
print("Barking")
d = Dog()
# d.bark() # 报错:多传了一个参数(实例 d)错误信息类似:TypeError: bark() takes 0 positional arguments but 1 was given。原因是 d.bark() 等价于 Dog.bark(d) 的绑定调用,会多出一个参数。
若不经过实例、直接用类对象调用,且方法确实不需要参数,则不会自动注入实例(但这就不是「实例方法」的常规用法了):
class Dog:
def bark():
print("Barking")
Dog.bark() # 可以:没有自动传入实例结论:需要访问实例状态或希望用 obj.method() 形式时,实例方法必须保留第一个参数(惯例命名为 self)。
与 cls、静态方法的区别
@classmethod:第一个参数是类本身,惯例命名为cls,由类.method()或实例.method()调用时传入对应类。@staticmethod:不自动传入实例或类,行为上接近普通函数,只是挂在类命名空间下。
class Dog:
def __init__(self, breed):
self.breed = breed
@classmethod
def walk(cls):
print("Dog is Walking")
def bark(self):
print(f"{self.breed} is barking.")
@staticmethod
def add(x, y):
return x + y
Dog.walk()
d = Dog("Labrador")
d.bark()
print(Dog.add(10, 20))输出:
Dog is Walking
Labrador is barking.
30参数名不必是 self / cls(仅作演示)
下面能运行,但强烈不建议在生产代码里这样写:
class Dog:
@classmethod
def walk(myclass):
print("Dog is Walking")
def bark(myobject):
print("Dog is Barking.")
Dog.walk()
d = Dog()
d.bark()可见:起作用的是「第一个形参的位置」,而不是名字本身;名字仍应用 self / cls 表达约定。
不同实例对应不同的 self
每个实例有自己的属性,self 指向谁,就读写谁的数据:
class Dog:
def __init__(self, b):
self.breed = b
def bark(self):
print(f"{self.breed} is Barking.")
d1 = Dog("Labrador")
d2 = Dog("Husky")
d1.bark()
d2.bark()输出:
Labrador is Barking.
Husky is Barking.为什么不让 self 像 this 一样隐式?
这是 Python 的早期设计选择:显式优于隐式——在方法签名里直接看到「会收到实例」,调用规则简单、也便于静态分析与元编程。常见问题见官方 Programming FAQ 中的说明(英文):What is self?。中文读者可查阅 常见问题 — 编程 中与类、self 相关的条目(若某小节仅有英文版,可对照英文 FAQ)。
历史上也有「是否把 self 改为关键字 / 隐式参数」的讨论,Guido van Rossum 曾明确倾向于保持显式写法;深入背景可在网上检索 Python explicit self、Guido self 等关键词。
小结
self:实例方法的第一个参数,代表当前实例,不是保留字。obj.method(a, b)会把obj传给self,再传a, b。@classmethod用cls;@staticmethod不要self/cls。- 工程里请始终使用
self/cls命名约定。