Python面向对象编程详解

1. 什么是面向对象编程

面向对象编程(OOP)是一种编程范式,它使用"对象"来设计应用程序。对象可以包含数据(属性)和代码(方法)。Python作为一门支持OOP的语言,提供了完整的面向对象特性,包括封装、继承和多态。

2. 类和对象

类是创建对象的蓝图,定义了一组属性和方法。对象是类的实例。

定义类的基本语法:

class Person:
    # 类属性
    species = 'Homo sapiens'

    # 初始化方法(构造函数)
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

    # 实例方法
    def introduce(self):
        return f"My name is {self.name}, I'm {self.age} years old."

    # 类方法
    @classmethod
    def get_species(cls):
        return f"Our species is {cls.species}."

创建对象(实例化):

# 创建Person类的实例
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

# 访问实例属性
print(person1.name)  # 输出: Alice
print(person2.age)   # 输出: 30

# 调用实例方法
print(person1.introduce())  # 输出: My name is Alice, I'm 25 years old.

# 调用类方法
print(Person.get_species())  # 输出: Our species is Homo sapiens.

3. 继承

继承允许我们创建一个新类,从现有类继承属性和方法,从而实现代码重用。

定义子类:

class Student(Person):
    def __init__(self, name, age, student_id):
        # 调用父类的初始化方法
        super().__init__(name, age)
        self.student_id = student_id

    # 重写父类方法
    def introduce(self):
        return f"{super().introduce()} My student ID is {self.student_id}."

    # 新增方法
    def study(self, subject):
        return f"{self.name} is studying {subject}."

使用子类:

student = Student("Charlie", 20, "S12345")
print(student.introduce())  # 输出: My name is Charlie, I'm 20 years old. My student ID is S12345.
print(student.study("Math"))  # 输出: Charlie is studying Math.

4. 封装

封装是指将数据和方法包装在类中,并限制对对象内部状态的直接访问。

使用私有属性和方法(以双下划线开头):

class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance  # 私有属性

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return f"Deposited ${amount}. New balance: ${self.__balance}"
        return "Invalid deposit amount."

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return f"Withdrew ${amount}. Remaining balance: ${self.__balance}"
        return "Invalid withdrawal amount."

    def get_balance(self):
        return self.__balance  # 通过方法访问私有属性

使用封装类:

account = BankAccount("David", 1000)
print(account.deposit(500))  # 输出: Deposited $500. New balance: $1500
print(account.withdraw(200))  # 输出: Withdrew $200. Remaining balance: $1300

# 尝试直接访问私有属性会报错
# print(account.__balance)  # AttributeError: 'BankAccount' object has no attribute '__balance'

# 通过方法访问
print(account.get_balance())  # 输出: 1300

5. 多态

多态允许不同类的对象对相同消息(方法调用)做出不同响应。

实现多态的例子:

class Animal:
    def speak(self):
        raise NotImplementedError("Subclass must implement this method")

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Duck(Animal):
    def speak(self):
        return "Quack!"

# 多态函数
def animal_sound(animal):
    return animal.speak()

使用多态:

dog = Dog()
cat = Cat()
duck = Duck()

print(animal_sound(dog))   # 输出: Woof!
print(animal_sound(cat))   # 输出: Meow!
print(animal_sound(duck))  # 输出: Quack!

6. 特殊方法(魔术方法)

特殊方法以双下划线开头和结尾,允许自定义类的行为。

常用特殊方法示例:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 字符串表示
    def __str__(self):
        return f"Vector({self.x}, {self.y})"

    # 加法运算符重载
    def __add__(self, other):
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        return NotImplemented

    # 等于运算符重载
    def __eq__(self, other):
        if isinstance(other, Vector):
            return self.x == other.x and self.y == other.y
        return False

    # 小于运算符重载
    def __lt__(self, other):
        if isinstance(other, Vector):
            return (self.x ** 2 + self.y ** 2) < (other.x ** 2 + other.y ** 2)
        return NotImplemented

使用特殊方法:

v1 = Vector(3, 4)
v2 = Vector(1, 2)
v3 = Vector(3, 4)

print(v1)          # 输出: Vector(3, 4)
print(v1 + v2)    # 输出: Vector(4, 6)
print(v1 == v3)   # 输出: True
print(v1 < v2)    # 输出: False

7. 静态方法和类方法

静态方法不接收类或实例作为第一个参数,行为类似于普通函数。

类方法接收类作为第一个参数(通常命名为cls)。

class MathUtils:
    # 静态方法
    @staticmethod
    def add(a, b):
        return a + b

    # 类方法
    @classmethod
    def multiply(cls, a, b):
        # 类方法可以访问类属性
        result = a * b
        print(f"Using {cls.__name__} to multiply {a} and {b}")
        return result

使用静态方法和类方法:

print(MathUtils.add(5, 3))          # 输出: 8
print(MathUtils.multiply(4, 6))    # 输出: Using MathUtils to multiply 4 and 6 然后输出: 24

8. 属性访问控制

使用@property装饰器可以创建只读属性或对属性访问添加逻辑。

class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self._last_name = last_name  # 约定俗成的受保护属性

    @property
    def full_name(self):
        """只读属性:全名"""
        return f"{self.first_name} {self._last_name}"

    @property
    def last_name(self):
        """带验证的属性访问"""
        return self._last_name

    @last_name.setter
    def last_name(self, value):
        """属性设置器"""
        if not value:
            raise ValueError("Last name cannot be empty")
        self._last_name = value

使用属性访问控制:

person = Person("John", "Doe")
print(person.full_name)  # 输出: John Doe

# 修改姓氏
person.last_name = "Smith"
print(person.full_name)  # 输出: John Smith

# 尝试设置无效值
try:
    person.last_name = ""
except ValueError as e:
    print(e)  # 输出: Last name cannot be empty

9. 抽象基类

抽象基类(ABC)定义接口规范,子类必须实现所有抽象方法。

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

    def describe(self):
        return "This is a shape"

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14 * self.radius

使用抽象基类:

circle = Circle(5)
print(circle.area())       # 输出: 78.5
print(circle.perimeter())  # 输出: 31.400000000000002
print(circle.describe())   # 输出: This is a shape

# 尝试实例化抽象基类会报错
try:
    shape = Shape()
except TypeError as e:
    print(e)  # 输出: Can't instantiate abstract class Shape with abstract methods area, perimeter

10. 总结

Python面向对象编程提供了强大的工具来组织代码、提高可重用性和可维护性。通过类和对象、继承、封装、多态等核心概念,以及特殊方法、属性访问控制和抽象基类等高级特性,我们可以构建灵活且结构良好的应用程序。掌握这些OOP原则和Python实现方式,将帮助你编写更清晰、更高效的代码,并在大型项目中更好地管理复杂性。

发表回复

后才能评论