不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。
python系列之面向对象编程
python系列前期章节
- python系列之注释与变量
- python系列之输入输出语句与数据类型
- python系列之运算符
- python系列之控制流程语句
- python系列之字符串
- python系列之列表
- python系列之元组
- python系列之字典
- python系列之集合
- python系列之函数基础
- python系列之函数进阶
- python系统之综合案例1:用python打造智能诗词生成助手
- python系列之综合案例2:用python开发《魔法学院入学考试》文字冒险游戏
- python系列之类与对象:面向对象编程(用造人计划秒懂面向对象)
- python系列之类与对象:python系列之详解面向对象的属性)
前言:当函数遇见对象,奇迹发生了!
想象一下,如果Python中的函数是超级英雄,那么当它们加入"对象战队"后,就变成了拥有超能力的方法!这些方法知道自己是哪个对象的一部分,可以访问对象的状态,并且能够与其他方法协同工作。
本文将带你探索Python面向对象编程中函数的奇妙世界,从基础方法到高级技巧,让你轻松掌握,笑对编程!
目录
- 实例方法:对象的行为能力
- 类方法:与类相关的操作
- 静态方法:独立的工具函数
- 特殊方法(魔术方法):让对象更Pythonic
- 方法重写与多态:子类的个性化
- 抽象方法:规定必须实现的行为
- 属性与方法:@property的妙用
- 方法解析顺序(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装饰器定义,它不需要self或cls参数,就像放在类中的普通函数。
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 | 访问和修改实例状态 |
| 类方法 | @classmethod | cls | 访问和修改类状态,工厂方法 |
| 静态方法 | @staticmethod | 无 | 与类和实例无关的工具函数 |
| 抽象方法 | @abstractmethod | self/cls | 在抽象基类中定义接口 |
| 特殊方法 | 无(双下划线) | varies | 支持Python内置操作 |
最佳实践与常见陷阱
-
合理使用方法类型
- 需要访问实例状态 → 实例方法
- 需要访问类状态或创建替代构造函数 → 类方法
- 不需要访问类或实例状态 → 静态方法
-
避免过度使用静态方法
# 不好:过度使用静态方法 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 -
合理使用继承和方法重写
# 不好:过度继承 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}正在烹饪美食")
✳ 记住,方法是对象的行为。通过灵活运用各种类型的方法,你可以创建出强大而灵活的类。现在,去赋予你的对象各种能力吧!
1240

被折叠的 条评论
为什么被折叠?



