Python面向对象:self参数的本质与绑定机制

一、开篇:每个实例方法都有的"隐形"参数
你已经在每个方法中写了几百次self了——但你有没有想过:为什么调用obj.method(arg)时,不需要显式传self?self到底是什么?可以不叫self吗?
⌨️ 先看一个颠覆你认知的例子:
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
return f"{self.name}: 汪汪!"
dog = Dog("旺财")
# 标准调用方式——你熟悉的
print(dog.bark()) # 旺财: 汪汪!
# 等价调用方式——揭示了self的真相
print(Dog.bark(dog)) # 旺财: 汪汪!
# Dog.bark是一个普通函数,需要手动传入self!
💡 self不是Python的关键字,而是一个约定俗成的参数名。Python在调用实例方法时,会自动把实例作为第一个参数传入——这就是self的来源。
二、self的底层机制
2.1 绑定方法与未绑定方法
class Person:
def greet(self, greeting="你好"):
return f"{greeting},我叫{self.name}"
p = Person()
p.name = "张三"
# 通过实例访问方法——得到的是"绑定方法"
bound = p.greet
print(type(bound)) # <class 'method'>
print(bound.__self__) # <__main__.Person object at …>
print(bound.__func__) # <function Person.greet at …>
print(bound("早上好")) # 早上好,我叫张三 —— self自动传入
# 通过类访问方法——得到的是普通函数
unbound = Person.greet
print(type(unbound)) # <class 'function'>
print(unbound(p, "晚上好")) # 晚上好,我叫张三 —— 需要手动传入self
# 💡 绑定方法 = 函数 + 绑定的实例
# 实例.method() 等价于 类.method(实例)
2.2 self不是关键字
# self不是Python关键字——只是一个约定
# 但全世界的Python程序员都使用self
class Example:
# ✅ 标准写法(全世界通用)
def method(self):
return self
# ⚠️ 可以改名(但不要这样做!)
def method2(this):
return this
def method3(me):
return me
def method4(the_instance):
return the_instance
e = Example()
print(e.method() is e) # True
print(e.method2() is e) # True —— 可以工作但让人困惑
print(e.method3() is e) # True
# 💡 虽然可以改名,但永远不要!self是Python社区最根深蒂固的约定
2.3 self在内存中的角色
class Point:
def __init__(self, x, y):
self.x = x # self指向当前被创建的实例
self.y = y
def distance_to_origin(self):
# self指向调用这个方法的那个实例
return (self.x ** 2 + self.y ** 2) ** 0.5
def move(self, dx, dy):
self.x += dx # 修改的是当前实例的属性
self.y += dy
# 创建两个实例
p1 = Point(3, 4)
p2 = Point(6, 8)
# 同一个方法,不同的self
print(p1.distance_to_origin()) # 5.0 —— self是p1
print(p2.distance_to_origin()) # 10.0 —— self是p2
# self让方法知道"我在操作哪个对象"
p1.move(1, 1)
print(p1.x, p1.y) # 4 5 —— p1被修改了
print(p2.x, p2.y) # 6 8 —— p2没有变化
三、self的实用场景
3.1 方法调用方法
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = balance
def deposit(self, amount):
"""存款"""
self._validate_amount(amount)
self._balance += amount
self._log("存款", amount)
def withdraw(self, amount):
"""取款"""
self._validate_amount(amount)
if amount > self._balance:
raise ValueError("余额不足")
self._balance -= amount
self._log("取款", amount)
def _validate_amount(self, amount):
"""私有方法——通过self调用"""
if amount <= 0:
raise ValueError("金额必须大于0")
def _log(self, action, amount):
"""私有方法"""
print(f"[{self.owner}] {action}: ¥{amount} 余额: ¥{self._balance}")
# 使用
acc = BankAccount("张三", 1000)
acc.deposit(500)
acc.withdraw(200)
3.2 返回self实现链式调用
class QueryBuilder:
"""查询构建器——方法返回self实现链式调用"""
def __init__(self):
self._table = ""
self._fields = ["*"]
self._conditions = []
self._order_by = ""
self._limit = None
def table(self, name):
self._table = name
return self # 返回self!
def select(self, *fields):
self._fields = list(fields)
return self
def where(self, condition):
self._conditions.append(condition)
return self
def order_by(self, field):
self._order_by = field
return self
def limit(self, n):
self._limit = n
return self
def build(self):
"""构建最终的SQL语句"""
sql = f"SELECT {', '.join(self._fields)} FROM {self._table}"
if self._conditions:
sql += " WHERE " + " AND ".join(self._conditions)
if self._order_by:
sql += f" ORDER BY {self._order_by}"
if self._limit:
sql += f" LIMIT {self._limit}"
return sql
# 链式调用——优雅!
query = (QueryBuilder()
.table("users")
.select("name", "email", "age")
.where("age > 18")
.where("status = 'active'")
.order_by("created_at DESC")
.limit(20)
.build())
print(query)
# SELECT name, email, age FROM users WHERE age > 18 AND status = 'active'
# ORDER BY created_at DESC LIMIT 20
四、常见错误
# ⚠️ 错误一:忘记写self参数
class Bad:
# def method(): # 忘记self!
# pass
# 调用 Bad().method() → TypeError: method() takes 0 positional arguments but 1 was given
pass
# ⚠️ 错误二:静态方法不需要self
class Utils:
@staticmethod
def add(a, b): # 没有self——这是静态方法
return a + b
print(Utils.add(3, 5)) # 8
# ⚠️ 错误三:类方法第一个参数是cls不是self
class MyClass:
@classmethod
def create(cls, name): # cls指代类本身
instance = cls()
instance.name = name
return instance
五、总结
self是Python OOP的基石。它让方法知道"我在操作哪个对象",是连接方法和实例的桥梁。
💡 核心要点:
✅ self是实例的"身份证"——每次调用方法,self告诉方法:“嘿,你现在操作的是我!”




