一、什么是 self?
self 是 Python 类中实例方法的第一个参数,它代表调用该方法的实例对象本身。通过 self,实例方法可以访问该实例的属性和其他方法。
classDog:
def__init__(self, name):
self.name = name # self 代表当前实例
defbark(self): # self 是实例方法的第一个参数
print(f"{self.name} 在汪汪叫")
dog = Dog("旺财")
dog.bark() # 旺财 在汪汪叫
二、self 的本质
当你调用 dog.bark() 时,Python 在底层做了这样的转换:Dog.bark(dog)。也就是说,self 就是调用该方法的实例对象本身。
classExample:
defshow(self):
print(f"self 是: {self}")
print(f"self 的类型: {type(self)}")
obj = Example()
obj.show()
# self 是: <__main__.Example object at 0x...>
# self 的类型: <class '__main__.Example'>
# 等价调用
Example.show(obj) # 与 obj.show() 效果相同
结论:self 不是关键字,它只是一个约定俗成的变量名(可以用其他名字,但强烈不推荐)。
三、self 的作用
3.1 访问实例属性
在实例方法内部,通过 self.属性名 可以访问该实例的属性。
classStudent:
def__init__(self, name, score):
self.name = name
self.score = score
defintroduce(self):
print(f"我叫 {self.name},成绩 {self.score}") # 通过 self 访问属性
s = Student("小明", 85)
s.introduce() # 我叫 小明,成绩 85
3.2 修改实例属性
同样通过 self.属性名 = 值 修改实例属性。
classBankAccount:
def__init__(self, balance):
self.balance = balance
defdeposit(self, amount):
self.balance += amount # 修改实例属性
defwithdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
acc = BankAccount(1000)
acc.deposit(500)
print(acc.balance) # 1500
3.3 调用其他实例方法
在实例方法内部,通过 self.方法名() 调用同一个实例的其他方法。
classRectangle:
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
returnself.width * self.height
defperimeter(self):
return2 * (self.width + self.height)
definfo(self):
a = self.area() # 调用实例方法
p = self.perimeter() # 调用实例方法
print(f"面积: {a}, 周长: {p}")
rect = Rectangle(4, 5)
rect.info() # 面积: 20, 周长: 18
四、self 的传递是自动的
在调用实例方法时,Python 会自动将实例对象作为第一个参数传递给方法。因此,定义实例方法时必须包含 self 参数,但调用时不需要也不能显式传递。
classTest:
defmethod(self, value):
print(f"self: {self}, value: {value}")
t = Test()
t.method(100) # self 自动传递,只需传 value
# 等价于: Test.method(t, 100)
五、self 不是关键字
self 只是一个约定俗称的参数名,理论上你可以使用任何名字(如 this、obj),但强烈建议遵循惯例使用 self,否则会降低代码可读性。
classExample:
def__init__(this, name): # 使用了 this,而不是 self
this.name = name
defshow(obj): # 使用了 obj
print(obj.name)
e = Example("测试")
e.show() # 测试
虽然能运行,但会让其他 Python 开发者困惑。始终使用 self 是最佳实践。
六、实例方法、类方法、静态方法中的 self
| | | |
| self | | |
| cls | | @classmethod |
| | | @staticmethod |
classDemo:
class_attr = 100
definstance_method(self):
print(f"实例方法: {self}")
@classmethod
defclass_method(cls):
print(f"类方法: {cls}")
@staticmethod
defstatic_method():
print("静态方法")
d = Demo()
d.instance_method() # self 指向实例 d
Demo.class_method() # cls 指向类 Demo
Demo.static_method() # 没有特殊参数
七、self 与实例属性的关系
所有实例属性都必须通过 self 来定义和访问。在 __init__ 中,通过 self.属性名 = 值 定义实例属性。在其他实例方法中,通过 self.属性名 访问。
classPerson:
def__init__(self, name, age):
self.name = name # 定义实例属性
self.age = age
defbirthday(self):
self.age += 1# 修改实例属性
print(f"{self.name} 现在 {self.age} 岁")
p = Person("张三", 25)
p.birthday() # 张三 现在 26 岁
注意:如果不使用 self,在方法中直接赋值创建的是局部变量,而不是实例属性。
classWrong:
def__init__(self, name):
name = name # 这是局部变量,不是实例属性
# self.name = name # 正确做法
w = Wrong("测试")
# print(w.name) # AttributeError
八、常见错误与注意事项
8.1 定义实例方法时忘记 self
classTest:
defmethod(): # 错误:缺少 self 参数
print("hello")
调用时会报错:TypeError: method() takes 0 positional arguments but 1 was given
8.2 调用实例方法时误传 self
t = Test()
t.method(t) # 错误:不需要手动传递 self
8.3 在类内部通过类名调用实例方法时,需要手动传递实例
classMyClass:
definstance_method(self):
print("实例方法")
defanother_method(self):
# 正确:通过 self 调用
self.instance_method()
# 错误:通过类名调用,需要手动传 self
# MyClass.instance_method() # TypeError
# 正确:手动传 self
MyClass.instance_method(self)
8.4 在类方法中误用 self
类方法的第一个参数是 cls,代表类,不是实例。在类方法中无法通过 self 访问实例属性。
classDemo:
@classmethod
defclass_method(cls):
# print(self.name) # 错误:self 不存在
print(cls.__name__) # 正确:使用 cls
九、总结
- •
self 是实例方法的第一个参数,代表调用该方法的实例对象。 - • 通过
self 可以在实例方法中访问和修改实例属性,调用其他实例方法。 - •
self 是自动传递的,调用时不需要也不能显式传递。 - •
self 只是一个约定俗成的名字(可以用其他名字,但强烈不推荐)。 - • 类方法的第一个参数是
cls,静态方法没有特殊参数。
核心理解:self 是连接实例方法和实例对象的桥梁。没有 self,实例方法就无法知道它正在操作哪个对象的数据。掌握 self 是理解 Python 面向对象编程的关键一步。