第54集:实例方法与self

学习目标

  • 理解实例方法的概念和作用
  • 掌握self参数的含义和用法
  • 学会通过self访问和修改实例属性
  • 理解实例方法、类方法、静态方法的区别
  • 掌握实例方法的调用方式
  • 学会在实例方法中调用其他方法

一、实例方法概述

1.1 什么是实例方法

实例方法:定义在类中,第一个参数是self的方法,用于操作对象的属性和执行对象的行为。

1.2 语法格式

class ClassName:
    def method_name(self, 参数1, 参数2, ...):
        # 方法体
        # 可以使用self访问和修改实例属性
        pass

1.3 基本示例

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def say_hello(self):
        """实例方法:自我介绍"""
        print(f"大家好,我是{self.name},今年{self.age}岁")

# 创建对象
p = Person("张三", 18)
p.say_hello()  # 输出:大家好,我是张三,今年18岁

二、self参数详解

2.1 self的含义

self代表什么:

  • self代表当前对象实例
  • 它是对调用方法的对象的引用

示例:

class Demo:
    def show_self(self):
        print(f"self的值: {self}")
        print(f"self的类型: {type(self)}")

d1 = Demo()
d1.show_self()
# 输出:
# self的值: <__main__.Demo object at 0x...>
# self的类型: <class '__main__.Demo'>

d2 = Demo()
d2.show_self()
# 输出:
# self的值: <__main__.Demo object at 0x...> (不同的地址)

2.2 self的自动传递

class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self, other):
        print(f"{self.name}向{other.name}打招呼")

p1 = Person("张三")
p2 = Person("李四")

# 方法调用时,Python自动传递对象作为self
p1.greet(p2)  # 实际上是: Person.greet(p1, p2)
# 输出:张三向李四打招呼

2.3 多个对象各自独立的self

class Counter:
    def __init__(self):
        self.count = 0
    
    def increment(self):
        self.count += 1
        print(f"当前计数: {self.count}")

c1 = Counter()
c2 = Counter()

c1.increment()  # 输出:当前计数: 1
c1.increment()  # 输出:当前计数: 2

c2.increment()  # 输出:当前计数: 1 (独立的)

三、通过self访问属性

3.1 访问实例属性

class Student:
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
    
    def display_info(self):
        """显示学生信息"""
        # 通过self访问实例属性
        print(f"姓名: {self.name}")
        print(f"年龄: {self.age}")
        print(f"成绩: {self.score}")

s = Student("张三", 18, 90)
s.display_info()

3.2 修改实例属性

class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    
    def deposit(self, amount):
        """存款"""
        # 通过self修改实例属性
        self.balance += amount
    
    def withdraw(self, amount):
        """取款"""
        self.balance -= amount

account = BankAccount(1000)
account.deposit(500)
print(account.balance)  # 输出:1500

account.withdraw(200)
print(account.balance)  # 输出:1300

3.3 动态添加属性

class Person:
    def __init__(self, name):
        self.name = name
    
    def add_attribute(self, attr_name, attr_value):
        """动态添加属性"""
        setattr(self, attr_name, attr_value)

p = Person("张三")
p.add_attribute("age", 18)
p.add_attribute("city", "北京")

print(p.age)   # 输出:18
print(p.city)  # 输出:北京

四、在实例方法中调用其他方法

4.1 调用其他实例方法

class Calculator:
    def __init__(self, value):
        self.value = value
    
    def add(self, other):
        self.value += other
        return self
    
    def multiply(self, other):
        self.value *= other
        return self
    
    def display(self):
        print(f"当前值: {self.value}")

calc = Calculator(10)
calc.add(5).multiply(2).display()
# 输出:当前值: 30

4.2 方法间的协作

class Student:
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores
    
    def calculate_average(self):
        """计算平均分"""
        if not self.scores:
            return 0
        return sum(self.scores) / len(self.scores)
    
    def get_grade(self):
        """获取等级"""
        average = self.calculate_average()  # 调用另一个方法
        if average >= 90:
            return "A"
        elif average >= 80:
            return "B"
        elif average >= 70:
            return "C"
        elif average >= 60:
            return "D"
        else:
            return "F"
    
    def display_report(self):
        """显示成绩报告"""
        print(f"学生: {self.name}")
        print(f"各科成绩: {self.scores}")
        print(f"平均分: {self.calculate_average():.2f}")
        print(f"等级: {self.get_grade()}")

s = Student("张三", [85, 90, 78, 92, 88])
s.display_report()

五、实例方法 vs 类方法 vs 静态方法

5.1 对比表

特性 实例方法 类方法 静态方法
第一个参数 self cls
装饰器 @classmethod @staticmethod
访问 实例属性和方法 类属性和方法 不访问属性
调用方式 对象名 类名或对象名 类名或对象名
用途 操作对象数据 操作类数据 工具函数

5.2 示例对比

class MyClass:
    class_attr = "类属性"
    
    def __init__(self):
        self.instance_attr = "实例属性"
    
    # 实例方法
    def instance_method(self):
        print(f"实例方法: self={self}")
        print(f"  实例属性: {self.instance_attr}")
        print(f"  类属性: {MyClass.class_attr}")
    
    # 类方法
    @classmethod
    def class_method(cls):
        print(f"类方法: cls={cls}")
        print(f"  类属性: {cls.class_attr}")
    
    # 静态方法
    @staticmethod
    def static_method():
        print("静态方法: 不访问任何属性")

# 使用
obj = MyClass()
obj.instance_method()
MyClass.class_method()
MyClass.static_method()

六、常见应用场景

6.1 数据处理

class DataProcessor:
    def __init__(self, data):
        self.data = data
    
    def filter(self, condition):
        """过滤数据"""
        return [item for item in self.data if condition(item)]
    
    def transform(self, func):
        """转换数据"""
        self.data = [func(item) for item in self.data]
        return self
    
    def aggregate(self, func):
        """聚合数据"""
        return func(self.data)

processor = DataProcessor([1, 2, 3, 4, 5])
result = processor.filter(lambda x: x > 2).transform(lambda x: x ** 2).aggregate(sum)
print(result)  # 输出:54 (3² + 4² + 5²)

6.2 状态管理

class GamePlayer:
    def __init__(self, name):
        self.name = name
        self.health = 100
        self.level = 1
        self.experience = 0
    
    def take_damage(self, damage):
        """受到伤害"""
        self.health -= damage
        if self.health < 0:
            self.health = 0
        print(f"{self.name}受到{damage}点伤害,剩余生命: {self.health}")
    
    def heal(self, amount):
        """治疗"""
        self.health += amount
        if self.health > 100:
            self.health = 100
        print(f"{self.name}恢复{amount}点生命,当前生命: {self.health}")
    
    def gain_experience(self, exp):
        """获得经验"""
        self.experience += exp
        if self.experience >= self.level * 100:
            self.level_up()
    
    def level_up(self):
        """升级"""
        self.level += 1
        self.health = 100  # 升级恢复满血
        print(f"{self.name}升级了!当前等级: {self.level}")

player = GamePlayer("英雄")
player.take_damage(30)
player.heal(20)
player.gain_experience(120)

七、常见错误与注意事项

7.1 常见错误

  1. 忘记self参数:
class Person:
    def say_hello():  # 错误:缺少self
        print("你好!")
  1. 调用方法时传递self:
class Person:
    def greet(self):
        print("你好!")

p = Person()
p.greet(p)  # 错误:不需要传递self
  1. 在类方法中错误使用self:
class MyClass:
    @classmethod
    def class_method(cls):
        self.value = 10  # 错误:类方法应该使用cls

7.2 注意事项

  1. 实例方法必须有self作为第一个参数
  2. 调用方法时不需要手动传递self
  3. 通过self可以访问所有实例属性和方法
  4. 一个对象的方法可以访问另一个对象的属性

八、课后练习

练习题

  1. 编程题

    • 定义一个Rectangle类,包含长和宽属性
    • 添加计算面积、周长的方法
    • 添加判断是否为正方形的方法
  2. 编程题

    • 定义一个BankAccount
    • 添加存款、取款、查询余额方法
    • 添加计算利息的方法
  3. 思考题

    • 为什么实例方法的第一个参数必须是self?
    • 类方法和实例方法有什么区别?
    • 什么时候应该使用静态方法?

九、本集总结

核心知识点回顾

  1. 实例方法:第一个参数是self的方法
  2. self的作用:代表当前对象实例
  3. 访问属性:通过self访问和修改实例属性
  4. 调用方法:在实例方法中调用其他实例方法
  5. 三种方法对比:实例方法、类方法、静态方法

下集预告

下一集我们将学习封装特性,深入了解如何使用访问修饰符来保护数据。


学习建议: 熟练掌握self的使用,理解实例方法的工作原理。通过编写实际的类来练习实例方法的应用。

« 上一篇 构造方法__init__ 下一篇 » 封装特性