Python教程41:面向对象最佳实践

Python教程41:面向对象最佳实践 “代码是写给人看的,顺便让机器执行。” 经过前面的学习,我们掌握了OOP的所有特性。今天总结Python面向对象的最佳实践,帮助你写出更优质的代码。 1. SOLID原则 S - 单一职责原则(Single Responsibility) 一个类只做一件事: 1# 不好:类职责太多 2class User: 3 def __init__(self, name): 4 self.name = name 5 6 def save_to_database(self): 7 """保存用户""" 8 pass 9 10 def send_email(self): 11 """发送邮件""" 12 pass 13 14# 好:职责分离 15class User: 16 def __init__(self, name): 17 self.name = name 18 19class UserRepository: 20 def save(self, user): 21 """保存用户""" 22 pass 23 24class EmailService: 25 def send(self, user): 26 """发送邮件""" 27 pass O - 开闭原则(Open/Closed) 对扩展开放,对修改关闭: 1# 好:使用多态扩展功能 2class Shape: 3 def area(self): 4 pass 5 6class Circle(Shape): 7 def __init__(self, radius): 8 self.radius = radius 9 10 def area(self): 11 return 3.14 * self.radius ** 2 12 13# 添加新形状无需修改现有代码 14class Rectangle(Shape): 15 def __init__(self, width, height): 16 self.width = width 17 self.height = height 18 19 def area(self): 20 return self.width * self.height L - 里氏替换原则(Liskov Substitution) 子类必须能替换父类: ...

2025-12-26 · 4 min · 727 words · 老墨

Python教程39:元类(Metaclass)

Python教程39:元类(Metaclass) “元类就是深度魔法,99%的用户应该根本不必为此操心。” —— Tim Peters 元类是Python的高级特性,用于创建类的"类"。今天我们揭开元类的神秘面纱,理解Python对象系统的底层机制。 1. 什么是元类 一切皆对象 在Python中,类也是对象: 1class MyClass: 2 pass 3 4# 类是对象 5print(type(MyClass)) # <class 'type'> 6print(isinstance(MyClass, type)) # True 7 8# 类可以赋值、作为参数 9AnotherName = MyClass 10def func(cls): 11 return cls() 元类(Metaclass): 创建类的"类" type是Python的默认元类 类是元类的实例 1# 类是type的实例 2class MyClass: 3 pass 4 5print(type(MyClass)) # <class 'type'> 6 7# 等价于 8MyClass = type('MyClass', (), {}) type的三种用法 1# 用法1:查看对象类型 2print(type(5)) # <class 'int'> 3 4# 用法2:动态创建类 5# type(name, bases, dict) 6MyClass = type('MyClass', (), {'x': 5}) 7obj = MyClass() 8print(obj.x) # 5 9 10# 用法3:作为元类(继承type) 11class MyMeta(type): 12 pass 2. 动态创建类 使用type动态创建类: ...

2025-11-13 · 4 min · 670 words · 老墨

Python教程38:多重继承与MRO

Python教程38:多重继承与MRO “大道至简,大巧若拙。” Python支持多重继承,一个类可以继承多个父类。今天我们学习多重继承的机制、方法解析顺序(MRO)以及如何避免常见陷阱。 1. 什么是多重继承 单继承 vs 多重继承 1# 单继承:一个父类 2class Parent: 3 pass 4 5class Child(Parent): 6 pass 7 8# 多重继承:多个父类 9class Father: 10 def skill(self): 11 return "父亲的技能" 12 13class Mother: 14 def talent(self): 15 return "母亲的天赋" 16 17class Child(Father, Mother): 18 """继承两个父类""" 19 pass 20 21# 子类拥有所有父类的方法 22c = Child() 23print(c.skill()) # 父亲的技能 24print(c.talent()) # 母亲的天赋 2. 方法解析顺序(MRO) 当多个父类有同名方法时,Python如何决定调用哪个? 基本规则 1class A: 2 def method(self): 3 return "A的方法" 4 5class B: 6 def method(self): 7 return "B的方法" 8 9class C(A, B): 10 """继承顺序:A, B""" 11 pass 12 13c = C() 14print(c.method()) # A的方法(优先使用第一个父类) 15 16# 查看MRO 17print(C.__mro__) 18# (<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>) MRO(Method Resolution Order): ...

2025-10-24 · 4 min · 646 words · 老墨

Python教程37:抽象基类(ABC)

Python教程37:抽象基类(ABC) “约定优于配置。” 抽象基类(Abstract Base Class, ABC)是Python中定义接口规范的机制。今天我们学习如何使用abc模块创建抽象类,强制子类实现特定方法。 1. 什么是抽象基类 问题场景 没有抽象类时,接口规范靠文档和约定: 1class Shape: 2 """ 3 形状基类 4 - 子类应该实现area()和perimeter() 5 - 但没有强制机制 6 """ 7 def area(self): 8 raise NotImplementedError("子类必须实现area方法") 9 10 def perimeter(self): 11 raise NotImplementedError("子类必须实现perimeter方法") 12 13class Circle(Shape): 14 def __init__(self, radius): 15 self.radius = radius 16 17 def area(self): 18 import math 19 return math.pi * self.radius ** 2 20 21 # 忘记实现perimeter()了! 22 23# 问题:可以实例化不完整的类 24c = Circle(5) 25print(c.area()) # OK 26# print(c.perimeter()) # 运行时才报错! 抽象基类解决方案 1from abc import ABC, abstractmethod 2 3class Shape(ABC): 4 """ 5 抽象形状类 6 - 继承ABC 7 - 使用@abstractmethod标记抽象方法 8 - 不能直接实例化 9 - 强制子类实现所有抽象方法 10 """ 11 12 @abstractmethod 13 def area(self): 14 """计算面积(抽象方法)""" 15 pass 16 17 @abstractmethod 18 def perimeter(self): 19 """计算周长(抽象方法)""" 20 pass 21 22class Circle(Shape): 23 def __init__(self, radius): 24 self.radius = radius 25 26 def area(self): 27 import math 28 return math.pi * self.radius ** 2 29 30 # 如果不实现perimeter(),无法实例化 31 32# circle = Shape() # TypeError: 无法实例化抽象类 33 34class CompleteCircle(Shape): 35 def __init__(self, radius): 36 self.radius = radius 37 38 def area(self): 39 import math 40 return math.pi * self.radius ** 2 41 42 def perimeter(self): 43 import math 44 return 2 * math.pi * self.radius 45 46# 完整实现所有抽象方法才能实例化 47c = CompleteCircle(5) 48print(c.area()) # 78.54 49print(c.perimeter()) # 31.42 ABC的优势: ...

2025-10-22 · 5 min · 1005 words · 老墨

Python教程36:属性(Property)与描述符

Python教程36:属性(Property)与描述符 “细节决定成败。” Python提供了强大的属性管理机制,让我们能够优雅地控制属性的访问。今天我们学习@property装饰器和描述符协议,掌握Python属性的高级用法。 1. 为什么需要Property 问题场景 直接访问属性缺乏控制: 1class Person: 2 def __init__(self, age): 3 self.age = age # 公开属性 4 5p = Person(25) 6print(p.age) # 25 7 8# 问题:可以设置非法值 9p.age = -10 # 负数年龄? 10p.age = "abc" # 字符串年龄? 传统解决方法:getter/setter 1class Person: 2 def __init__(self, age): 3 self._age = age # 私有属性 4 5 def get_age(self): 6 """获取年龄""" 7 return self._age 8 9 def set_age(self, value): 10 """设置年龄(带验证)""" 11 if not isinstance(value, int): 12 raise TypeError("年龄必须是整数") 13 if value < 0 or value > 150: 14 raise ValueError("年龄不合理") 15 self._age = value 16 17p = Person(25) 18print(p.get_age()) # 25 19p.set_age(30) # OK 20# p.set_age(-10) # ValueError 问题: 使用不方便:p.get_age()而不是p.age 破坏现有代码:如果后来添加验证,需要修改所有调用 Python解决方案:@property 1class Person: 2 def __init__(self, age): 3 self._age = age 4 5 @property 6 def age(self): 7 """ 8 getter方法 9 - 像访问属性一样调用:p.age 10 - 但实际调用的是方法 11 """ 12 return self._age 13 14 @age.setter 15 def age(self, value): 16 """ 17 setter方法 18 - 像赋值一样调用:p.age = 30 19 - 可以添加验证逻辑 20 """ 21 if not isinstance(value, int): 22 raise TypeError("年龄必须是整数") 23 if value < 0 or value > 150: 24 raise ValueError("年龄不合理") 25 self._age = value 26 27# 使用 28p = Person(25) 29print(p.age) # 调用getter:25 30p.age = 30 # 调用setter:OK 31# p.age = -10 # ValueError 优势: ...

2025-09-14 · 8 min · 1524 words · 老墨

Python教程35:类方法与静态方法

Python教程35:类方法与静态方法 “工欲善其事,必先利其器。” Python提供了三种方法类型:实例方法、类方法、静态方法。今天我们学习类方法(@classmethod)和静态方法(@staticmethod),理解它们的区别和使用场景。 1. 三种方法类型对比 实例方法(Instance Method) 我们最常用的方法: 1class MyClass: 2 def instance_method(self): 3 """ 4 实例方法 5 - 第一个参数是self(实例本身) 6 - 可以访问实例属性和类属性 7 - 通过实例调用 8 """ 9 print(f"Called instance_method of {self}") 10 return "instance method" 11 12obj = MyClass() 13obj.instance_method() # 正常调用 类方法(Class Method) 使用@classmethod装饰器: 1class MyClass: 2 @classmethod 3 def class_method(cls): 4 """ 5 类方法 6 - 第一个参数是cls(类本身) 7 - 可以访问类属性,不能访问实例属性 8 - 通过类或实例调用 9 """ 10 print(f"Called class_method of {cls}") 11 return "class method" 12 13# 通过类调用 14MyClass.class_method() 15 16# 通过实例调用也可以 17obj = MyClass() 18obj.class_method() 静态方法(Static Method) 使用@staticmethod装饰器: ...

2025-08-26 · 6 min · 1150 words · 老墨

Python教程34:魔术方法(Magic Methods)

Python教程34:魔术方法(Magic Methods) “命名即魔法。” Python的魔术方法(也叫特殊方法、双下划线方法)是Python面向对象的核心特性。它们让你的类能够像内置类型一样工作,实现运算符重载、容器协议等高级功能。 1. 什么是魔术方法 魔术方法(Magic Methods): 双下划线开头和结尾的方法:__method__ Python自动调用,不需要显式调用 让类支持Python的特殊语法 也叫"dunder methods"(double underscore) 为什么需要魔术方法: 运算符重载:让对象支持+、-、*等运算 容器协议:让对象可迭代、可索引 上下文管理:支持with语句 对象表示:自定义打印输出 属性访问:控制属性读写 简单示例 1class Point: 2 """二维点""" 3 def __init__(self, x, y): 4 """初始化(魔术方法)""" 5 self.x = x 6 self.y = y 7 8 def __str__(self): 9 """字符串表示(魔术方法)""" 10 return f"Point({self.x}, {self.y})" 11 12 def __add__(self, other): 13 """加法运算符(魔术方法)""" 14 return Point(self.x + other.x, self.y + other.y) 15 16# 使用 17p1 = Point(1, 2) 18p2 = Point(3, 4) 19 20print(p1) # 调用__str__: Point(1, 2) 21p3 = p1 + p2 # 调用__add__ 22print(p3) # Point(4, 6) 2. 对象创建和销毁 new:创建实例 1class Singleton: 2 """ 3 单例模式 4 - __new__在__init__之前调用 5 - __new__负责创建实例 6 - __new__是类方法 7 """ 8 _instance = None 9 10 def __new__(cls): 11 """ 12 创建实例 13 - cls是类本身 14 - 必须返回实例 15 """ 16 if cls._instance is None: 17 print("Creating singleton instance") 18 cls._instance = super().__new__(cls) 19 return cls._instance 20 21 def __init__(self): 22 """初始化实例""" 23 print("Initializing instance") 24 25# 使用 26s1 = Singleton() # Creating singleton instance, Initializing instance 27s2 = Singleton() # Initializing instance (不创建新实例) 28print(s1 is s2) # True(同一个实例) init:初始化 我们已经很熟悉了: ...

2025-07-28 · 8 min · 1524 words · 老墨

Python教程33:多态

Python教程33:多态 “一个接口,多种实现。” 多态是面向对象编程三大特性(封装、继承、多态)的最后一个。今天我们学习Python的多态特性,理解如何让代码更灵活、更易扩展。 1. 什么是多态 多态(Polymorphism): Poly(多个)+ morph(形态) 同一个接口,不同的实现 不同对象对同一消息的不同响应 为什么需要多态: 灵活性:通过父类引用调用子类方法 可扩展:添加新类无需修改现有代码 统一接口:不同对象用相同方式操作 解耦合:调用者不关心对象类型 简单示例 1class Animal: 2 """动物基类""" 3 def speak(self): 4 pass 5 6class Dog(Animal): 7 def speak(self): 8 return "Woof!" 9 10class Cat(Animal): 11 def speak(self): 12 return "Meow!" 13 14class Cow(Animal): 15 def speak(self): 16 return "Moo!" 17 18# 多态:相同的方法调用,不同的行为 19def animal_sound(animal): 20 """ 21 统一的接口 22 - 参数是Animal类型 23 - 不关心具体是什么动物 24 - 调用speak()得到不同的结果 25 """ 26 print(animal.speak()) 27 28# 使用 29animals = [Dog(), Cat(), Cow()] 30for animal in animals: 31 animal_sound(animal) 32# 输出: 33# Woof! 34# Meow! 35# Moo! 多态的好处: ...

2025-06-24 · 5 min · 987 words · 老墨

Python教程32:继承

Python教程32:继承 “站在巨人的肩膀上。” 继承是面向对象编程的三大特性之一(封装、继承、多态),它让我们可以基于已有类创建新类,实现代码复用。今天我们深入学习Python的继承机制。 1. 什么是继承 问题场景 假设要创建多个类: 1# 没有继承:代码重复 2class Dog: 3 def __init__(self, name, age): 4 self.name = name 5 self.age = age 6 7 def eat(self): 8 return f"{self.name} is eating" 9 10class Cat: 11 def __init__(self, name, age): 12 self.name = name 13 self.age = age 14 15 def eat(self): 16 return f"{self.name} is eating" 17 18 def meow(self): 19 return "Meow!" 20 21# 重复的代码... 继承(Inheritance): 子类继承父类的属性和方法 子类可以添加新的属性和方法 子类可以重写父类的方法 实现代码复用,减少重复 为什么需要继承: 代码复用:共享功能写一次 逻辑清晰:体现is-a关系(狗是动物) 易于维护:修改父类,所有子类受益 扩展性强:基于现有代码扩展新功能 继承的基本语法 1class ParentClass: 2 """父类(基类、超类)""" 3 pass 4 5class ChildClass(ParentClass): 6 """子类(派生类)""" 7 pass 2. 基本继承 简单示例 1class Animal: 2 """动物类(父类)""" 3 4 def __init__(self, name, age): 5 """初始化动物""" 6 self.name = name 7 self.age = age 8 9 def eat(self): 10 """吃东西(所有动物都会吃)""" 11 return f"{self.name} is eating" 12 13 def sleep(self): 14 """睡觉""" 15 return f"{self.name} is sleeping" 16 17class Dog(Animal): 18 """狗类(子类)- 继承Animal""" 19 20 def bark(self): 21 """狗叫(狗特有的方法)""" 22 return f"{self.name} says: Woof!" 23 24class Cat(Animal): 25 """猫类(子类)- 继承Animal""" 26 27 def meow(self): 28 """猫叫(猫特有的方法)""" 29 return f"{self.name} says: Meow!" 30 31# 使用 32dog = Dog("Buddy", 3) 33print(dog.eat()) # 继承自Animal:Buddy is eating 34print(dog.bark()) # Dog自己的方法:Buddy says: Woof! 35 36cat = Cat("Whiskers", 2) 37print(cat.eat()) # 继承自Animal:Whiskers is eating 38print(cat.meow()) # Cat自己的方法:Whiskers says: Meow! 继承的特点: ...

2025-05-10 · 6 min · 1135 words · 老墨

Python教程31:类与对象基础

Python教程31:类与对象基础 “万物皆对象。” 从今天开始,我们进入Python编程的新境界——面向对象编程(OOP)。这是一种组织代码的强大范式,让程序更贴近真实世界的思维方式。 1. 什么是面向对象编程 编程范式的演进 面向过程编程(Procedural Programming): 以函数为中心 数据和操作分离 适合简单问题 1# 面向过程:管理学生信息 2students = [ 3 {"name": "Alice", "age": 20, "grade": 85}, 4 {"name": "Bob", "age": 21, "grade": 90} 5] 6 7def calculate_average(students): 8 """计算平均成绩""" 9 total = sum(s["grade"] for s in students) 10 return total / len(students) 11 12# 数据和操作分离 面向对象编程(Object-Oriented Programming, OOP): 以对象为中心 数据和操作封装在一起 更贴近真实世界建模 1# 面向对象:学生类 2class Student: 3 """学生类:数据和行为封装在一起""" 4 def __init__(self, name, age, grade): 5 self.name = name 6 self.age = age 7 self.grade = grade 8 9 def get_info(self): 10 """学生的行为""" 11 return f"{self.name}, {self.age}岁, 成绩{self.grade}" 12 13# 创建对象 14alice = Student("Alice", 20, 85) 15bob = Student("Bob", 21, 90) OOP的核心概念 类(Class): ...

2025-04-17 · 5 min · 1004 words · 老墨