2024-05-16 · 阅读约 21 分钟 · 阅读

9. 面向对象编程

面向对象编程(OOP)是一种编程范式,使用“对象”来组织代码。对象是类的实例,类定义了对象的属性和方法。

类和对象

  • 类是对象的蓝图或模板,定义了对象的属性和行为。
# 定义一个类
class Dog: # 相当于Dog(object)
    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.age = age
  
    # 实例方法
    def bark(self):
        print(f"{self.name} is barking")

# 创建对象(实例)
my_dog = Dog("Buddy", 3)

# 访问对象属性
print(my_dog.name)  # 输出 "Buddy"
print(my_dog.age)   # 输出 3

# 调用对象方法
my_dog.bark()  # 输出 "Buddy is barking"

继承

  • 继承是面向对象编程的一个重要特性,允许一个类继承另一个类的属性和方法。基类(父类)和派生类(子类)之间存在继承关系。
# 定义基类
class Animal:
    def __init__(self, name):
        self.name = name
  
    def speak(self):
        print(f"{self.name} is making a sound")

# 定义派生类
class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color
  
    def speak(self):
        print(f"{self.name} is meowing")

# 创建派生类对象
my_cat = Cat("Whiskers", "white")

# 访问派生类对象属性和方法
print(my_cat.name)   # 输出 "Whiskers"
print(my_cat.color)  # 输出 "white"
my_cat.speak()       # 输出 "Whiskers is meowing"

多态

多态是指不同类的对象可以通过相同的接口调用方法,产生不同的行为。通常通过方法重载实现。

# 示例代码
class Bird(Animal):
    def speak(self):
        print(f"{self.name} is chirping")

# 定义一个函数,接受一个动物对象
def animal_speak(animal):
    animal.speak()

# 创建不同的动物对象
dog = Dog("Buddy", 3)
cat = Cat("Whiskers", "white")
bird = Bird("Tweety")

# 调用函数
animal_speak(dog)   # 输出 "Buddy is barking"
animal_speak(cat)   # 输出 "Whiskers is meowing"
animal_speak(bird)  # 输出 "Tweety is chirping"

封装

封装是指将对象的属性和方法私有化,保护对象的内部状态不被外部直接访问和修改。通过定义公有和私有方法和属性实现封装。

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

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
        else:
            print("存款金额必须大于零")

    def withdraw(self, amount):
        if amount <= self.__balance:
            self.__balance -= amount
        else:
            print("余额不足")

    def get_balance(self):
        return self.__balance

# 创建对象
account = BankAccount("Alice", 1000)

# 访问公有属性和方法
print(account.owner)  # 输出 "Alice"
account.deposit(500)
account.withdraw(200)
print(account.get_balance())  # 输出 1300

# 试图访问私有属性(会报错)
# print(account.__balance)

通过掌握面向对象编程的基本概念和技巧,你可以编写更具结构化、可扩展性和可维护性的代码。

私有属性

在面向对象编程中,让类属性能够被直接访问是危险的。使用私有属性可以保证属性不能被直接访问修改,增强安全性。私有属性用__(双下划线)前缀进行标识。

#-- coding:UTF-8 --
# 定义一个类
class Dog:
    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.__age = age # __age为私有属性


# 创建对象(实例)
my_dog = Dog("Buddy", 3)

# 访问对象属性
print(my_dog.name)  # 输出 "Buddy"
#print(my_dog.__age)   # 无法访问

# 强制访问私有属性
print(my_dog._Dog__age)

10. 高级主题

装饰器

  • 装饰器是一种用于修改或增强函数行为的高级技术。它本质上是一个函数,接受一个函数作为参数,并返回一个新的函数。
# 定义装饰器
def my_decorator(func):
    def wrapper():
        print("在函数执行之前")
        func()
        print("在函数执行之后")
    return wrapper

# 使用装饰器
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
  • 在这个示例中,my_decorator 装饰器在 say_hello 函数的执行前后添加了额外的打印语句。

  • 装饰器可以接受参数,以提供更灵活的功能。

# 定义带参数的装饰器
def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")
  • 在这个示例中,repeat 装饰器接受参数 num_times,并重复执行 say_hello 函数指定的次数。

生成器

  • 生成器是一种特殊的迭代器,使用 yield 关键字生成值。与普通函数不同,生成器在每次生成值后暂停,并在下次调用时继续执行。
# 定义生成器
def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

# 使用生成器
counter = count_up_to(5)
for num in counter:
    print(num)
  • 在这个示例中,count_up_to 生成器每次生成一个数值,并在达到 max 值时停止。

高阶生成器

  • 生成器可以与其他生成器组合使用,以创建复杂的数据处理管道。
def generator1():
    yield from range(3)

def generator2():
    yield from range(3, 6)

# 组合生成器
def combined_generator():
    yield from generator1()
    yield from generator2()

for value in combined_generator():
    print(value)

Lambda函数

  • Lambda函数是一种简洁的匿名函数,用于定义简单的函数。常用于需要一个短期函数的场景。
# 示例代码
add = lambda x, y: x + y
print(add(3, 5))  # 输出 8

列表推导式

  • 列表推导式是一种创建列表的简洁方法,可以在一行代码中生成列表。
# 示例代码
squares = [x**2 for x in range(10)]
print(squares)  # 输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

面向对象编程的高级特性

  • 包括类方法静态方法属性装饰器等。
# 示例代码
class MyClass:
    class_variable = "I am a class variable"
  
    def __init__(self, instance_variable):
        self.instance_variable = instance_variable
  
    @classmethod # 类方法
    def class_method(cls):
        return cls.class_variable
  
    @staticmethod # 静态方法
    def static_method():
        return "I am a static method"
  
    @property # 属性装饰器
    def instance_property(self):
        return self.instance_variable

obj = MyClass("I am an instance variable")
print(MyClass.class_method())      # 输出 "I am a class variable"
print(MyClass.static_method())     # 输出 "I am a static method"
print(obj.instance_property)       # 输出 "I am an instance variable"

1. 类方法(Class Method)

类方法使用 @classmethod 装饰器定义,第一个参数是类本身,通常命名为 cls。类方法可以访问类变量和修改类状态。

class MyClass:
    class_variable = "I am a class variable"

    def __init__(self, instance_variable):
        self.instance_variable = instance_variable

    @classmethod
    def class_method(cls):
        return cls.class_variable

# 使用类方法
print(MyClass.class_method())  # 输出 "I am a class variable"

在这个示例中,class_method 是一个类方法,它返回类变量 class_variable 的值。

2. 静态方法(Static Method)

静态方法使用 @staticmethod 装饰器定义,不需要传入类或实例作为参数。静态方法通常用于执行一些逻辑操作,这些操作与类和实例无关。

class MyClass:

    @staticmethod
    def static_method():
        return "I am a static method"

# 使用静态方法
print(MyClass.static_method())  # 输出 "I am a static method"

在这个示例中,static_method 是一个静态方法,它不访问类或实例的数据,仅执行独立的逻辑。

3. 属性装饰器(Property Decorator)

属性装饰器 @property 允许你将类的方法转换为只读属性,使得你可以像访问属性一样访问方法。这使得类的设计更直观和易于使用。

1. 基本用法

使用 @property 可以定义一个只读属性。

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

    @property  # 将方法转换为属性
    def radius(self):
        return self._radius

# 创建对象并访问属性
c = Circle(5)
print(c.radius)  # 输出 5

在这个示例中,radius 方法被转换为一个只读属性,因此你可以像访问属性一样访问它,而不需要调用方法。

2. 设置器(Setter)

除了只读属性,属性装饰器还可以定义属性的设置器,允许你在设置属性值时执行一些额外的逻辑。使用 @<property_name>.setter 装饰器来定义设置器。

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

    @property
    def radius(self):
        return self._radius

    @radius.setter  # 定义设置器
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

# 创建对象并设置属性
c = Circle(5)
print(c.radius)  # 输出 5
c.radius = 10
print(c.radius)  # 输出 10
# c.radius = -1  # 会引发 ValueError: 半径不能为负数

在这个示例中,radius 属性有一个设置器,当尝试设置负值时会引发异常。

3. 删除器(Deleter)

同样地,你还可以定义属性的删除器,使用 @<property_name>.deleter 装饰器来定义删除器。

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

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

    @radius.deleter  # 定义删除器
    def radius(self):
        print("删除半径属性")
        del self._radius

# 创建对象并删除属性
c = Circle(5)
print(c.radius)  # 输出 5
del c.radius
# print(c.radius)  # 会引发 AttributeError: 'Circle' object has no attribute '_radius'

在这个示例中,radius 属性有一个删除器,当属性被删除时会执行特定的逻辑。

4. 完整示例

一个包含所有三种方法的完整示例如下:

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

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

    @radius.deleter
    def radius(self):
        print("删除半径属性")
        del self._radius

# 使用属性装饰器
c = Circle(5)
print(c.radius)  # 输出 5
c.radius = 10
print(c.radius)  # 输出 10
del c.radius

通过使用属性装饰器,你可以使类的接口更加直观和易于使用,同时能够控制属性的访问和修改。

11. 数据科学与机器学习库

1. NumPy

NumPy 是一个用于科学计算的库,支持多维数组和矩阵运算,提供了大量的数学函数。

import numpy as np

# 创建数组
array = np.array([1, 2, 3, 4, 5])
print(array)

# 数组运算
print(array + 10)
print(array * 2)

2. pandas

pandas 是一个数据分析和处理库,提供了高性能的数据结构和数据分析工具。

import pandas as pd

# 创建数据框
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35]}
df = pd.DataFrame(data)
print(df)

# 数据框操作
print(df['Name'])
print(df.describe())

3. matplotlib

matplotlib 是一个绘图库,用于创建静态、动态和交互式的图表。

import matplotlib.pyplot as plt

# 创建数据
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]

# 绘制折线图
plt.plot(x, y)
plt.xlabel('x轴')
plt.ylabel('y轴')
plt.title('折线图示例')
plt.show()

4. scikit-learn

scikit-learn 是一个用于机器学习的库,提供了简单高效的数据挖掘和数据分析工具。

from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建并训练模型
model = LogisticRegression()
model.fit(X_train, y_train)

# 预测并评估模型
y_pred = model.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred)}")

12. 高级主题

装饰器

  • 装饰器是一种用于修改或增强函数行为的高级技术。它本质上是一个函数,接受一个函数作为参数,并返回一个新的函数。
# 定义装饰器
def my_decorator(func):
    def wrapper():
        print("在函数执行之前")
        func()
        print("在函数执行之后")
    return wrapper

# 使用装饰器
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
  • 在这个示例中,my_decorator 装饰器在 say_hello 函数的执行前后添加了额外的打印语句。

  • 装饰器可以接受参数,以提供更灵活的功能。

# 定义带参数的装饰器
def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")
  • 在这个示例中,repeat 装饰器接受参数 num_times,并重复执行 say_hello 函数指定的次数。

生成器

  • 生成器是一种特殊的迭代器,使用 yield 关键字生成值。与普通函数不同,生成器在每次生成值后暂停,并在下次调用时继续执行。
# 定义生成器
def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

# 使用生成器
counter = count_up_to(5)
for num in counter:
    print(num)
  • 在这个示例中,count_up_to 生成器每次生成一个数值,并在达到 max 值时停止。

高阶生成器

  • 生成器可以与其他生成器组合使用,以创建复杂的数据处理管道。
def generator1():
    yield from range(3)

def generator2():
    yield from range(3, 6)

# 组合生成器
def combined_generator():
    yield from generator1()
    yield from generator2()

for value in combined_generator():
    print(value)

Lambda函数

  • Lambda函数是一种简洁的匿名函数,用于定义简单的函数。常用于需要一个短期函数的场景。
# 示例代码
add = lambda x, y: x + y
print(add(3, 5))  # 输出 8

列表推导式

  • 列表推导式是一种创建列表的简洁方法,可以在一行代码中生成列表。
# 示例代码
squares = [x**2 for x in range(10)]
print(squares)  # 输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

面向对象编程的高级特性

  • 包括类方法静态方法属性装饰器等。
# 示例代码
class MyClass:
    class_variable = "I am a class variable"
  
    def __init__(self, instance_variable):
        self.instance_variable = instance_variable
  
    @classmethod # 类方法
    def class_method(cls):
        return cls.class_variable
  
    @staticmethod # 静态方法
    def static_method():
        return "I am a static method"
  
    @property # 属性装饰器
    def instance_property(self):
        return self.instance_variable

obj = MyClass("I am an instance variable")
print(MyClass.class_method())      # 输出 "I am a class variable"
print(MyClass.static_method())     # 输出 "I am a static method"
print(obj.instance_property)       # 输出 "I am an instance variable"

1. 类方法(Class Method)

类方法使用 @classmethod 装饰器定义,第一个参数是类本身,通常命名为 cls。类方法可以访问类变量和修改类状态。

class MyClass:
    class_variable = "I am a class variable"

    def __init__(self, instance_variable):
        self.instance_variable = instance_variable

    @classmethod
    def class_method(cls):
        return cls.class_variable

# 使用类方法
print(MyClass.class_method())  # 输出 "I am a class variable"

在这个示例中,class_method 是一个类方法,它返回类变量 class_variable 的值。

2. 静态方法(Static Method)

静态方法使用 @staticmethod 装饰器定义,不需要传入类或实例作为参数。静态方法通常用于执行一些逻辑操作,这些操作与类和实例无关。

class MyClass:

    @staticmethod
    def static_method():
        return "I am a static method"

# 使用静态方法
print(MyClass.static_method())  # 输出 "I am a static method"

在这个示例中,static_method 是一个静态方法,它不访问类或实例的数据,仅执行独立的逻辑。

3. 属性装饰器(Property Decorator)

属性装饰器 @property 允许你将类的方法转换为只读属性,使得你可以像访问属性一样访问方法。这使得类的设计更直观和易于使用。

1. 基本用法

使用 @property 可以定义一个只读属性。

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

    @property  # 将方法转换为属性
    def radius(self):
        return self._radius

# 创建对象并访问属性
c = Circle(5)
print(c.radius)  # 输出 5

在这个示例中,radius 方法被转换为一个只读属性,因此你可以像访问属性一样访问它,而不需要调用方法。

2. 设置器(Setter)

除了只读属性,属性装饰器还可以定义属性的设置器,允许你在设置属性值时执行一些额外的逻辑。使用 @<property_name>.setter 装饰器来定义设置器。

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

    @property
    def radius(self):
        return self._radius

    @radius.setter  # 定义设置器
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

# 创建对象并设置属性
c = Circle(5)
print(c.radius)  # 输出 5
c.radius = 10
print(c.radius)  # 输出 10
# c.radius = -1  # 会引发 ValueError: 半径不能为负数

在这个示例中,radius 属性有一个设置器,当尝试设置负值时会引发异常。

3. 删除器(Deleter)

同样地,你还可以定义属性的删除器,使用 @<property_name>.deleter 装饰器来定义删除器。

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

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

    @radius.deleter  # 定义删除器
    def radius(self):
        print("删除半径属性")
        del self._radius

# 创建对象并删除属性
c = Circle(5)
print(c.radius)  # 输出 5
del c.radius
# print(c.radius)  # 会引发 AttributeError: 'Circle' object has no attribute '_radius'

在这个示例中,radius 属性有一个删除器,当属性被删除时会执行特定的逻辑。

4. 完整示例

一个包含所有三种方法的完整示例如下:

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

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("半径不能为负数")
        self._radius = value

    @radius.deleter
    def radius(self):
        print("删除半径属性")
        del self._radius

# 使用属性装饰器
c = Circle(5)
print(c.radius)  # 输出 5
c.radius = 10
print(c.radius)  # 输出 10
del c.radius

通过使用属性装饰器,你可以使类的接口更加直观和易于使用,同时能够控制属性的访问和修改。