深入python 类和对象编程范式

Python中,类和对象是面向对象编程(Object-Oriented Programming, OOP)的核心概念。理解类和对象的基本概念及其工作原理对于编写结构良好、易于维护的代码至关重要。

概念

类是一种用户定义的类型,它描述了一组具有相同属性(数据成员)和行为(方法)的对象。类定义了一个对象的蓝图,它指定了如何创建该类型的对象。

定义类

class MyClass:    # 类变量,所有实例共享    class_var = "This is a class variable."    def __init__(self, instance_var):        # 实例变量,每个实例独立        self.instance_var = instance_var    def method(self):        # 实例方法,可以访问实例变量        print(f"This is an instance method. Instance variable: {self.instance_var}")

对象的概念

对象是类的一个实例。当你创建一个类的实例时,实际上是根据该类的定义分配内存,并初始化该对象的属性。

创建对象

# 创建MyClass的一个实例obj = MyClass("This is an instance variable.")# 访问对象的属性print(obj.instance_var)  # 输出: This is an instance variable.# 调用对象的方法obj.method()  # 输出: This is an instance method. Instance variable: This is an instance variable.

类的成员

1. 实例变量

实例变量是在__init__方法中定义的变量,它们属于每个实例,每个实例都有自己的一份副本。

2. 类变量

类变量是在类定义体中定义的变量,它们不属于任何一个实例,而是所有实例共享的。通常用于存储所有对象共有的信息。

3. 方法

方法是与类关联的函数,它们可以访问和修改实例变量。Python中的方法默认接受第一个参数self,它是指向实例本身的引用。

继承

继承是面向对象编程的一个重要特性,它允许一个类继承另一个类的属性和方法。子类可以覆盖或扩展基类的行为。

基础示例

class Animal:    def speak(self):        raise NotImplementedError("Subclass must implement this abstract method")class Dog(Animal):    def speak(self):        return "Woof!"class Cat(Animal):    def speak(self):        return "Meow!"# 创建Dog和Cat的实例dog = Dog()cat = Cat()# 调用speak方法print(dog.speak())  # 输出: Woof!print(cat.speak())  # 输出: Meow!

在这个例子中,Dog和Cat都继承自Animal类,并且覆盖了speak方法。

特殊方法

Python有一些特殊的方法,也称为魔术方法或Dunder(double underscore)方法,它们用于定义类的行为,例如如何比较对象、如何表示对象等。

常见的特殊方法

__init__(self, ...):初始化方法,当创建一个新实例时被调用。

__str__(self):返回一个描述对象的易读字符串。

__repr__(self):返回一个包含对象信息的字符串,主要用于调试。

__eq__(self, other):定义对象相等的条件。

__lt__(self, other):定义小于操作符 < 的行为。

__add__(self, other):定义加法操作的行为。

基础示例

class Point:    def __init__(self, x=0, y=0):        self.x = x        self.y = y    def __str__(self):        return f"Point({self.x}, {self.y})"    def __repr__(self):        return f"Point(x={self.x}, y={self.y})"    def __eq__(self, other):        return self.x == other.x and self.y == other.y    def __add__(self, other):        return Point(self.x + other.x, self.y + other.y)# 创建两个点p1 = Point(1, 2)p2 = Point(3, 4)# 使用特殊方法print(p1)          # 输出: Point(1, 2)print(repr(p1))    # 输出: Point(x=1, y=2)print(p1 == p2)    # 输出: Falseprint(p1 + p2)     # 输出: Point(4, 6)

类和对象进阶示例

使用封装和属性访问控制

在这个示例中,我们将展示如何使用私有属性和属性访问器方法来保护类的内部状态。

class BankAccount:    def __init__(self, balance=0):        self.__balance = balance    def deposit(self, amount):        if amount > 0:            self.__balance += amount        else:            raise ValueError("Deposit amount must be positive.")    def withdraw(self, amount):        if amount > 0 and amount <= self.__balance:            self.__balance -= amount        else:            raise ValueError("Withdrawal amount must be positive and less than or equal to the current balance.")    def get_balance(self):        return self.__balance# 创建账户实例account = BankAccount()# 存款account.deposit(1000)# 提款account.withdraw(500)# 获取余额print(account.get_balance())  # 输出: 500

在这个例子中,我们使用双下划线前缀(__balance)来声明一个私有属性,外部代码无法直接访问或修改这个属性。我们提供了deposit、withdraw和get_balance方法来控制对这个属性的操作。

使用继承和多态

在这个示例中,我们将展示如何使用继承来创建具有共同特征的不同类,并通过多态来实现方法的重写。

class Animal:    def __init__(self, name):        self.name = name    def speak(self):        raise NotImplementedError("Subclass must implement this abstract method")class Dog(Animal):    def speak(self):        return f"{self.name} says Woof!"class Cat(Animal):    def speak(self):        return f"{self.name} says Meow!"# 创建动物实例dog = Dog("Buddy")cat = Cat("Whiskers")# 调用speak方法print(dog.speak())  # 输出: Buddy says Woof!print(cat.speak())  # 输出: Whiskers says Meow!# 多态示例def animal_sound(animal):    print(animal.speak())animal_sound(dog)  # 输出: Buddy says Woof!animal_sound(cat)  # 输出: Whiskers says Meow!

在这个例子中,Dog和Cat类都继承自Animal类,并且覆盖了speak方法。animal_sound函数接收一个Animal类型的参数,并调用speak方法,这展示了多态的概念——不同类型的对象可以以相同的方式被对待。

使用特殊方法实现运算符重载

在这个示例中,我们将展示如何使用特殊方法来实现运算符重载,使自定义类能够像内置类型一样支持加法、减法等操作。

class Vector:    def __init__(self, x=0, y=0):        self.x = x        self.y = y    def __add__(self, other):        return Vector(self.x + other.x, self.y + other.y)    def __sub__(self, other):        return Vector(self.x - other.x, self.y - other.y)    def __str__(self):        return f"Vector({self.x}, {self.y})"# 创建向量实例v1 = Vector(1, 2)v2 = Vector(3, 4)# 向量加法result_add = v1 + v2print(result_add)  # 输出: Vector(4, 6)# 向量减法result_sub = v1 - v2print(result_sub)  # 输出: Vector(-2, -2)

在这个例子中,我们定义了Vector类,并实现了__add__和__sub__特殊方法,使得两个Vector对象可以相加或相减。

使用类方法和静态方法

在这个示例中,我们将展示如何使用类方法和静态方法来扩展类的功能。

class Employee:    num_of_employees = 0    raise_amount = 1.04    def __init__(self, first, last, pay):        self.first = first        self.last = last        self.email = f"{first}.{last}@company.com"        self.pay = pay        Employee.num_of_employees += 1    def fullname(self):        return f"{self.first} {self.last}"    def apply_raise(self):        self.pay = int(self.pay * self.raise_amount)    @classmethod    def set_raise_amount(cls, amount):        cls.raise_amount = amount    @classmethod    def from_string(cls, emp_str):        first, last, pay = emp_str.split("-")        return cls(first, last, pay)    @staticmethod    def is_workday(day):        if day.weekday() == 5 or day.weekday() == 6:            return False        return True# 创建员工实例emp_1 = Employee("John", "Doe", 60000)emp_2 = Employee("Jane", "Smith", 70000)# 使用类方法Employee.set_raise_amount(1.05)print(Employee.raise_amount)  # 输出: 1.05# 使用类方法从字符串创建实例emp_str_1 = "Michael-Brown-70000"new_emp = Employee.from_string(emp_str_1)print(new_emp.email)  # 输出: Michael.Brown@company.com# 使用静态方法import datetimemy_date = datetime.date(2024, 9, 16)print(Employee.is_workday(my_date))  # 输出: True 或 False,取决于日期

在这个例子中,我们定义了Employee类,并实现了类方法和静态方法。类方法set_raise_amount用于设置所有员工的加薪比例,from_string用于从字符串创建员工实例,静态方法is_workday用于判断给定日期是否为工作日。

来源:测试开发学习交流

THE END