面向对象基础
High Contrast
Dark Mode
Light Mode
Sepia
Forest
3 min read505 words

面向对象基础

设计模式基于面向对象编程(OOP),掌握OOP基础是学习设计模式的前提。本章将回顾面向对象的核心概念,为后续学习做准备。

类与对象

类的定义

(Class)是对象的蓝图,定义了对象的属性和方法。

class Person:
"""人类"""
# 类属性
species = "人类"
def __init__(self, name, age):
"""构造方法"""
self.name = name  # 实例属性
self.age = age
def introduce(self):
"""实例方法"""
return f"我叫{self.name},今年{self.age}岁"
@classmethod
def get_species(cls):
"""类方法"""
return cls.species
@staticmethod
def is_adult(age):
"""静态方法"""
return age >= 18

对象的创建

# 创建对象(实例化)
person1 = Person("张三", 25)
person2 = Person("李四", 30)
# 访问属性
print(person1.name)  # 张三
print(person2.age)   # 30
# 调用方法
print(person1.introduce())  # 我叫张三,今年25岁
print(Person.get_species())  # 人类
print(Person.is_adult(20))   # True

四大特性

1. 封装(Encapsulation)

封装是将数据和方法包装在一起,并隐藏内部实现细节。

class BankAccount:
"""银行账户 - 演示封装"""
def __init__(self, initial_balance):
self.__balance = initial_balance  # 私有属性
def deposit(self, amount):
"""存款"""
if amount > 0:
self.__balance += amount
return True
return False
def withdraw(self, amount):
"""取款"""
if 0 < amount <= self.__balance:
self.__balance -= amount
return True
return False
def get_balance(self):
"""查询余额(只读访问)"""
return self.__balance
# 使用
account = BankAccount(1000)
account.deposit(500)
account.withdraw(200)
print(account.get_balance())  # 1300
# 无法直接修改余额
# account.__balance = 0  # 这样不行!

封装的好处: - ✅ 保护数据不被非法修改 - ✅ 隐藏实现细节 - ✅ 提供统一的访问接口

2. 继承(Inheritance)

继承是从已有类创建新类,实现代码复用。

class Animal:
"""动物基类"""
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现speak方法")
def eat(self):
return f"{self.name}正在吃东西"
class Dog(Animal):
"""狗类 - 继承Animal"""
def speak(self):
return f"{self.name}:汪汪!"
class Cat(Animal):
"""猫类 - 继承Animal"""
def speak(self):
return f"{self.name}:喵喵!"
# 使用
dog = Dog("旺财")
cat = Cat("咪咪")
print(dog.speak())  # 旺财:汪汪!
print(cat.eat())    # 咪咪正在吃东西

继承的关系:

          Animal
/      \
Dog      Cat

3. 多态(Polymorphism)

多态是同一方法在不同对象上有不同行为。

class Shape:
"""形状基类"""
def draw(self):
raise NotImplementedError
class Circle(Shape):
def draw(self):
return "画一个圆形"
class Rectangle(Shape):
def draw(self):
return "画一个矩形"
class Triangle(Shape):
def draw(self):
return "画一个三角形"
def draw_shape(shape: Shape):
"""统一接口,处理不同形状"""
print(shape.draw())
# 多态调用
shapes = [Circle(), Rectangle(), Triangle()]
for shape in shapes:
draw_shape(shape)
# 输出:
# 画一个圆形
# 画一个矩形
# 画一个三角形

4. 抽象(Abstraction)

抽象是隐藏复杂细节,只暴露必要的接口。

from abc import ABC, abstractmethod
class Vehicle(ABC):
"""交通工具抽象类"""
@abstractmethod
def start(self):
"""启动"""
pass
@abstractmethod
def stop(self):
"""停止"""
pass
def get_info(self):
"""非抽象方法"""
return "这是一个交通工具"
class Car(Vehicle):
"""汽车"""
def start(self):
return "汽车启动"
def stop(self):
return "汽车停止"
class Bike(Vehicle):
"""自行车"""
def start(self):
return "骑行开始"
def stop(self):
return "骑行结束"
# 不能直接实例化抽象类
# vehicle = Vehicle()  # 报错!
car = Car()
print(car.start())  # 汽车启动
print(car.get_info())  # 这是一个交通工具

方法类型

graph TB A[方法类型] --> B[实例方法] A --> C[类方法] A --> D[静态方法] B --> B1[self作为第一个参数] B --> B2[访问实例和类属性] B --> B3[最常用的方法] C --> C1[cls作为第一个参数] C --> C2[只能访问类属性] C --> C3[@classmethod装饰器] D --> D1[无特殊参数] D --> D2[不访问任何属性] D --> D3[@staticmethod装饰器] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style B fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style C fill:#fff9c4,stroke:#f9a825,stroke-width:2px style D fill:#c8e6c9,stroke:#43a047,stroke-width:2px

示例对比

class Calculator:
"""计算器类"""
PI = 3.14159
def __init__(self, value):
self.value = value
def add(self, x):
"""实例方法:使用self"""
return self.value + x
@classmethod
def circle_area(cls, radius):
"""类方法:使用cls"""
return cls.PI * radius ** 2
@staticmethod
def is_even(number):
"""静态方法:无self/cls"""
return number % 2 == 0
# 使用
calc = Calculator(10)
# 实例方法
print(calc.add(5))  # 15
# 类方法(通过类或实例调用)
print(Calculator.circle_area(5))  # 78.53975
print(calc.circle_area(5))        # 78.53975
# 静态方法
print(Calculator.is_even(4))  # True
print(calc.is_even(3))        # False

鸭子类型(Duck Typing)

Python 的鸭子类型:"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。"

class Duck:
def speak(self):
return "嘎嘎嘎"
class Person:
def speak(self):
return "说话"
def make_sound(thing):
"""只要对象有speak方法就可以"""
print(thing.speak())
# 不需要继承或实现接口
make_sound(Duck())    # 嘎嘎嘎
make_sound(Person())  # 说话

鸭子类型让代码更灵活,但也需要开发者约定好接口规范。

属性访问控制

graph LR A[属性] --> B[public] A --> C[_protected] A --> D[__private] B --> B1[公开] C --> C1[保护(约定)] D --> D1[私有(名称改写)] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style B fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style C fill:#fff9c4,stroke:#f9a825,stroke-width:2px style D fill:#c8e6c9,stroke:#43a047,stroke-width:2px
class Example:
def __init__(self):
self.public = "公开属性"
self._protected = "保护属性"  # 约定:内部使用
self.__private = "私有属性"  # 名称改写:_Example__private
obj = Example()
print(obj.public)        # ✅ 公开属性
print(obj._protected)    # ⚠️ 可以访问,但不推荐
# print(obj.__private)  # ❌ 报错:AttributeError
# Python的"私有"通过名称改写实现
print(obj._Example__private)  # ✅ 私有属性(通过改写后的名称访问)

魔术方法

魔术方法(Magic Methods)是以双下划线开头和结尾的特殊方法,用于实现自定义行为。

class Vector:
"""向量类 - 演示魔术方法"""
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
"""str()输出"""
return f"Vector({self.x}, {self.y})"
def __repr__(self):
"""repr()输出(调试用)"""
return f"Vector(x={self.x}, y={self.y})"
def __add__(self, other):
"""+运算符"""
return Vector(self.x + other.x, self.y + other.y)
def __len__(self):
"""len()函数"""
return int((self.x ** 2 + self.y ** 2) ** 0.5)
def __getitem__(self, index):
"""索引访问"""
if index == 0:
return self.x
elif index == 1:
return self.y
else:
raise IndexError("索引超出范围")
# 使用
v1 = Vector(3, 4)
v2 = Vector(1, 2)
print(str(v1))          # Vector(3, 4)
print(repr(v1))         # Vector(x=3, y=4)
v3 = v1 + v2            # 调用 __add__
print(v3)               # Vector(4, 6)
print(len(v1))          # 5
print(v1[0])            # 3
print(v1[1])            # 4

类的继承层次

graph TB A[object] --> B[Base Class] B --> C[Subclass A] B --> D[Subclass B] C --> E[Sub-subclass] D --> F[Subclass B2] style A fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style B fill:#fff9c4,stroke:#f9a825,stroke-width:2px style C fill:#c8e6c9,stroke:#43a047,stroke-width:2px style D fill:#c8e6c9,stroke:#43a047,stroke-width:2px style E fill:#a5d6a7,stroke:#2e7d32,stroke-width:2px style F fill:#a5d6a7,stroke:#2e7d32,stroke-width:2px

super()函数

super() 用于调用父类方法。

class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "动物叫声"
class Dog(Animal):
def __init__(self, name, breed):
# 调用父类的__init__
super().__init__(name)
self.breed = breed
def speak(self):
# 调用父类方法并扩展
base_sound = super().speak()
return f"{base_sound}(汪汪)"
dog = Dog("旺财", "哈士奇")
print(dog.name)   # 旺财
print(dog.breed)  # 哈士奇
print(dog.speak()) # 动物叫声(汪汪)

多重继承

Python 支持多重继承,但需要谨慎使用。

class Flyable:
def fly(self):
return "会飞"
class Swimmable:
def swim(self):
return "会游泳"
class Duck(Flyable, Swimmable):
def speak(self):
return "嘎嘎嘎"
duck = Duck()
print(duck.fly())    # 会飞
print(duck.swim())   # 会游泳
print(duck.speak())  # 嘎嘎嘎

本章要点


下一步SOLID原则 🚀