python系列之详解面向对象的函数

不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。

python系列前期章节

  1. python系列之注释与变量
  2. python系列之输入输出语句与数据类型
  3. python系列之运算符
  4. python系列之控制流程语句
  5. python系列之字符串
  6. python系列之列表
  7. python系列之元组
  8. python系列之字典
  9. python系列之集合
  10. python系列之函数基础
  11. python系列之函数进阶
  12. python系统之综合案例1:用python打造智能诗词生成助手
  13. python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
  14. python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
  15. python系列之类与对象:python系列之详解面向对象的属性)

前言:当函数遇见对象,奇迹发生了!

想象一下,如果Python中的函数是超级英雄,那么当它们加入"对象战队"后,就变成了拥有超能力的方法!这些方法知道自己是哪个对象的一部分,可以访问对象的状态,并且能够与其他方法协同工作。

本文将带你探索Python面向对象编程中函数的奇妙世界,从基础方法到高级技巧,让你轻松掌握,笑对编程!

目录

  1. 实例方法:对象的行为能力
  2. 类方法:与类相关的操作
  3. 静态方法:独立的工具函数
  4. 特殊方法(魔术方法):让对象更Pythonic
  5. 方法重写与多态:子类的个性化
  6. 抽象方法:规定必须实现的行为
  7. 属性与方法:@property的妙用
  8. 方法解析顺序(MRO):多重继承的解决方案

1. 实例方法:对象的行为能力

实例方法是最常见的方法类型,它们可以访问和修改对象的属性。

基本实例方法

class Robot:
	# 初始化
    def __init__(self, name):
        self.name = name
        self.battery = 100
    
    # 实例方法
    def introduce(self):
        print(f"你好,我是{self.name},电量剩余{self.battery}%")
    
    # 另一个实例方法
    def work(self, hours):
        consumption = hours * 10
        if self.battery >= consumption:
            self.battery -= consumption
            print(f"{self.name}工作了{hours}小时,消耗{consumption}%电量")
        else:
            print(f"{self.name}电量不足,无法工作!")

# 创建机器人实例
wall_e = Robot("瓦力")
wall_e.introduce()  # 输出: 你好,我是瓦力,电量剩余100%
wall_e.work(3)      # 输出: 瓦力工作了3小时,消耗30%电量
wall_e.introduce()  # 输出: 你好,我是瓦力,电量剩余70%

self参数:方法的秘密武器

self参数是实例方法的第一个参数,它指向调用该方法的对象实例。Python会自动传递这个参数,你不需要手动传递。

class Robot:
    def __init__(self, name):
        self.name = name
    
    def say_hello(self, to_who):
        print(f"{self.name}{to_who}说:你好!")

robot = Robot("大白")
robot.say_hello("小朋友")  # 输出: 大白对小朋友说:你好!
# 注意:我们只传递了一个参数(to_who),self是自动传递的

2. 类方法:与类相关的操作

类方法使用@classmethod装饰器定义,第一个参数是cls,指向类本身而不是实例。

class Robot:
    count = 0  # 类属性
    
    def __init__(self, name):
        self.name = name
        Robot.count += 1
    
    @classmethod
    def how_many(cls):
        print(f"已经创建了{cls.count}个机器人")
    
    @classmethod
    def create_from_config(cls, config):
        # 类方法可以作为替代构造函数
        name = config.get('name', '无名机器人')
        return cls(name)

# 使用类方法
Robot.how_many()  # 输出: 已经创建了0个机器人

r1 = Robot("阿尔法")
r2 = Robot("贝塔")

Robot.how_many()  # 输出: 已经创建了2个机器人

# 使用类方法作为工厂方法
config = {'name': '伽马'}
r3 = Robot.create_from_config(config)
Robot.how_many()  # 输出: 已经创建了3个机器人

3. 静态方法:独立的工具函数

静态方法使用@staticmethod装饰器定义,它不需要selfcls参数,就像放在类中的普通函数。

class Robot:
    def __init__(self, name, x=0, y=0):
        self.name = name
        self.x = x
        self.y = y
    
    @staticmethod
    def calculate_distance(x1, y1, x2, y2):
        """计算两点之间的距离"""
        return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
    
    def distance_to(self, other_robot):
        """计算到另一个机器人的距离"""
        return self.calculate_distance(self.x, self.y, 
                                      other_robot.x, other_robot.y)

# 使用静态方法
distance = Robot.calculate_distance(0, 0, 3, 4)
print(f"两点之间的距离是: {distance}")  # 输出: 5.0

# 创建两个机器人
r1 = Robot("R2-D2", 0, 0)
r2 = Robot("C-3PO", 3, 4)

# 计算它们之间的距离
print(f"{r1.name}{r2.name}之间的距离: {r1.distance_to(r2)}")  # 输出: 5.0

4. 特殊方法(魔术方法):让对象更Pythonic

特殊方法以双下划线开头和结尾,它们让对象可以支持Python内置操作。

常见魔术方法

class Robot:
	# 类的初始化
    def __init__(self, name, power):
        self.name = name
        self.power = power
    
    # 字符串表示,一般为类的输出
    def __str__(self):
        return f"机器人{self.name}(能量: {self.power})"
    
    def __repr__(self):
        return f"Robot('{self.name}', {self.power})"
    
    # 比较运算符
    def __eq__(self, other):
        return self.power == other.power
    
    def __lt__(self, other):
        return self.power < other.power
    
    # 数学运算
    def __add__(self, other):
        # 合并两个机器人的能量
        new_name = f"{self.name}-{other.name}"
        new_power = self.power + other.power
        return Robot(new_name, new_power)
    
    # 调用对象
    def __call__(self, task):
        print(f"{self.name}正在执行任务: {task}")

# 使用魔术方法
r1 = Robot("雷霆", 50)
r2 = Robot("风暴", 70)

print(r1)  # 输出: 机器人雷霆(能量: 50)
print(r1 == r2)  # 输出: False
print(r1 < r2)   # 输出: True

r3 = r1 + r2  # 调用__add__
print(r3)      # 输出: 机器人雷霆-风暴(能量: 120)

r1("打扫房间")  # 输出: 雷霆正在执行任务: 打扫房间

5. 方法重写与多态:子类的个性化

子类可以重写父类的方法,以实现特定的行为,这是面向对象编程中多态性的体现。

class Robot:
    def __init__(self, name):
        self.name = name
    
    def perform_task(self):
        print(f"{self.name}正在执行通用任务")

class CleaningRobot(Robot):
    def perform_task(self):
        print(f"{self.name}正在打扫房间")

class CookingRobot(Robot):
    def perform_task(self):
        print(f"{self.name}正在烹饪美食")

# 多态:不同类型的机器人执行相同的操作,但行为不同
robots = [Robot("通用"), CleaningRobot("清洁者"), CookingRobot("厨师")]
for robot in robots:
    robot.perform_task()

# 输出:
# 通用正在执行通用任务
# 清洁者正在打扫房间
# 厨师正在烹饪美食

6. 抽象方法:规定必须实现的行为

抽象方法定义在抽象基类(ABC)中,要求子类必须实现这些方法。

from abc import ABC, abstractmethod

class Robot(ABC):
    def __init__(self, name):
        self.name = name
    
    @abstractmethod
    def perform_task(self):
        pass  # 子类必须实现这个方法
    
    def introduce(self):
        print(f"我是{self.name}")

class CleaningRobot(Robot):
    def perform_task(self):
        print(f"{self.name}正在打扫房间")

# 如果子类没有实现抽象方法,会报错
class LazyRobot(Robot):
    pass

# 正确使用
cleaner = CleaningRobot("清洁者")
cleaner.introduce()   # 输出: 我是清洁者
cleaner.perform_task()  # 输出: 清洁者正在打扫房间

# 错误使用
# lazy = LazyRobot("懒虫")  # TypeError: Can't instantiate abstract class...

7. 属性与方法:@property的妙用

@property装饰器可以将方法转换为属性,使你可以使用属性语法调用方法。

class Robot:
    def __init__(self, name, battery=100):
        self.name = name
        self._battery = battery
    
    @property
    def battery_status(self):
        """将电池电量转换为描述性状态"""
        if self._battery > 70:
            return "电量充足"
        elif self._battery > 30:
            return "电量中等"
        else:
            return "电量不足,请充电"
    
    @property
    def battery(self):
        return self._battery
    
    @battery.setter
    def battery(self, value):
        if 0 <= value <= 100:
            self._battery = value
        else:
            raise ValueError("电量必须在0-100之间")
    
    @battery.deleter
    def battery(self):
        print("备份电量数据...")
        self._battery = 0

robot = Robot("瓦力", 50)
print(robot.battery_status)  # 输出: 电量中等
print(robot.battery)         # 输出: 50

robot.battery = 80           # 使用setter
print(robot.battery)         # 输出: 80

del robot.battery            # 使用deleter,输出: 备份电量数据...
print(robot.battery)         # 输出: 0

8. 方法解析顺序(MRO):多重继承的解决方案

当类存在多重继承时,Python使用C3线性化算法确定方法解析顺序。

class A:
    def method(self):
        print("A的方法")

class B(A):
    def method(self):
        print("B的方法")
        super().method()

class C(A):
    def method(self):
        print("C的方法")
        super().method()

class D(B, C):
    def method(self):
        print("D的方法")
        super().method()

# 查看方法解析顺序
print(D.__mro__)
# 输出: (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

d = D()
d.method()
# 输出:
# D的方法
# B的方法
# C的方法
# A的方法

总结:方法使用速查表

方法类型装饰器第一个参数用途
实例方法self访问和修改实例状态
类方法@classmethodcls访问和修改类状态,工厂方法
静态方法@staticmethod与类和实例无关的工具函数
抽象方法@abstractmethodself/cls在抽象基类中定义接口
特殊方法无(双下划线)varies支持Python内置操作

最佳实践与常见陷阱

  1. 合理使用方法类型

    • 需要访问实例状态 → 实例方法
    • 需要访问类状态或创建替代构造函数 → 类方法
    • 不需要访问类或实例状态 → 静态方法
  2. 避免过度使用静态方法

    # 不好:过度使用静态方法
    class MathUtils:
        @staticmethod
        def add(a, b):
            return a + b
        
        @staticmethod
        def subtract(a, b):
            return a - b
    
    # 好:使用模块级函数
    def add(a, b):
        return a + b
    
    def subtract(a, b):
        return a - b
    
  3. 合理使用继承和方法重写

    # 不好:过度继承
    class Robot:
        pass
    
    class CleaningRobot(Robot):
        pass
    
    class CookingRobot(Robot):
        pass
    
    # 好:考虑组合而不是继承
    class Robot:
        def __init__(self, name, task_behavior):
            self.name = name
            self.task_behavior = task_behavior
        
        def perform_task(self):
            self.task_behavior.perform(self.name)
    
    class CleaningBehavior:
        def perform(self, name):
            print(f"{name}正在打扫房间")
    
    class CookingBehavior:
        def perform(self, name):
            print(f"{name}正在烹饪美食")
    

✳ 记住,方法是对象的行为。通过灵活运用各种类型的方法,你可以创建出强大而灵活的类。现在,去赋予你的对象各种能力吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值