7、Python高级特性 - 提升代码质量与效率

Python高级特性 - 提升代码质量与效率

1. 高级特性概述

作为Java开发者,您已经掌握了面向对象编程的核心概念。Python除了支持这些基本概念外,还提供了许多高级特性,可以让您的代码更加简洁、高效和优雅。这些特性在Java中可能没有直接对应物,或者实现起来比较复杂。

2. 装饰器(Decorators)

装饰器是Python中非常强大的特性,允许您修改函数或类的行为,而不需要直接修改其源代码。

graph TD A[原始函数] -->|应用装饰器| B[装饰器函数] B -->|接收函数作为参数| C[定义包装函数] C -->|添加额外功能| D[返回包装函数] D -->|替换原始函数| E[增强的函数] style A fill:#d0e0ff,stroke:#333,stroke-width:2px style B fill:#ffe0d0,stroke:#333,stroke-width:2px style C fill:#d0ffe0,stroke:#333,stroke-width:2px style D fill:#ffd0e0,stroke:#333,stroke-width:2px style E fill:#e0d0ff,stroke:#333,stroke-width:2px

基本装饰器

python 复制代码
# 定义装饰器
def timer(func):
    """测量函数执行时间的装饰器"""
    import time
    
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"函数 {func.__name__} 执行时间: {end_time - start_time:.6f} 秒")
        return result
    
    return wrapper

# 使用装饰器
@timer
def slow_function():
    """一个执行较慢的函数"""
    import time
    time.sleep(1)
    return "完成"

# 调用函数
result = slow_function()
print(result)

带参数的装饰器

python 复制代码
# 带参数的装饰器
def repeat(n=1):
    """重复执行函数n次的装饰器"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(n):
                results.append(func(*args, **kwargs))
            return results
        return wrapper
    return decorator

# 使用带参数的装饰器
@repeat(3)
def greet(name):
    return f"你好,{name}!"

# 调用函数
results = greet("张三")
print(results)  # 输出: ['你好,张三!', '你好,张三!', '你好,张三!']

类装饰器

python 复制代码
# 类装饰器
class CountCalls:
    """计算函数调用次数的装饰器类"""
    def __init__(self, func):
        self.func = func
        self.count = 0
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"函数 {self.func.__name__} 已被调用 {self.count} 次")
        return self.func(*args, **kwargs)

# 使用类装饰器
@CountCalls
def say_hello():
    return "你好!"

# 调用函数
print(say_hello())
print(say_hello())
print(say_hello())

装饰器链

python 复制代码
# 多个装饰器可以链式应用
@timer
@repeat(2)
def complex_operation(x, y):
    import time
    time.sleep(0.5)
    return x + y

# 调用函数
result = complex_operation(10, 20)
print(result)

保留原函数元数据

使用functools.wraps保留被装饰函数的元数据:

python 复制代码
from functools import wraps

def logger(func):
    @wraps(func)  # 保留原函数的元数据
    def wrapper(*args, **kwargs):
        print(f"调用函数: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logger
def add(a, b):
    """将两个数相加"""
    return a + b

# 查看函数元数据
print(add.__name__)  # 输出: add(而不是wrapper)
print(add.__doc__)   # 输出: 将两个数相加

3. 生成器(Generators)

生成器是一种特殊的迭代器,可以按需生成值,而不是一次性生成所有值,从而节省内存。

生成器函数

使用yield语句创建生成器函数:

python 复制代码
def count_up_to(max):
    """生成从1到max的数字"""
    count = 1
    while count <= max:
        yield count
        count += 1

# 使用生成器
counter = count_up_to(5)
print(next(counter))  # 输出: 1
print(next(counter))  # 输出: 2

# 在循环中使用生成器
for number in count_up_to(5):
    print(number)  # 输出: 1, 2, 3, 4, 5

生成器表达式

类似于列表推导式,但使用圆括号而不是方括号:

python 复制代码
# 列表推导式(一次性生成所有值)
squares_list = [x**2 for x in range(1000000)]  # 占用大量内存

# 生成器表达式(按需生成值)
squares_gen = (x**2 for x in range(1000000))  # 内存高效

# 使用生成器表达式
print(next(squares_gen))  # 输出: 0
print(next(squares_gen))  # 输出: 1

# 在循环中使用生成器表达式
for square in (x**2 for x in range(5)):
    print(square)  # 输出: 0, 1, 4, 9, 16

生成器的send方法

生成器可以通过send方法接收外部值:

python 复制代码
def echo_generator():
    """回声生成器:返回发送给它的值"""
    response = yield "准备好接收值"
    while True:
        response = yield f"你说: {response}"

# 使用生成器的send方法
gen = echo_generator()
print(next(gen))  # 输出: 准备好接收值(启动生成器)
print(gen.send("你好"))  # 输出: 你说: 你好
print(gen.send("Python很棒"))  # 输出: 你说: Python很棒

生成器的应用:数据流处理

python 复制代码
def read_large_file(file_path, chunk_size=1024):
    """分块读取大文件"""
    with open(file_path, 'r') as f:
        while True:
            data = f.read(chunk_size)
            if not data:
                break
            yield data

def grep(pattern, lines):
    """过滤包含指定模式的行"""
    import re
    pattern = re.compile(pattern)
    for line in lines:
        if pattern.search(line):
            yield line

def count_words(lines):
    """计算每行的单词数"""
    for line in lines:
        yield len(line.split())

# 使用生成器进行数据流处理
def process_log_file(file_path, pattern):
    # 读取文件
    chunks = read_large_file(file_path)
    # 将块分割成行
    lines = (line for chunk in chunks for line in chunk.splitlines())
    # 过滤包含指定模式的行
    matching_lines = grep(pattern, lines)
    # 计算单词数
    word_counts = count_words(matching_lines)
    # 计算总单词数
    return sum(word_counts)

4. 迭代器(Iterators)

迭代器是实现了__iter____next__方法的对象,可以被用于for循环。

创建自定义迭代器

python 复制代码
class Countdown:
    """从n倒数到1的迭代器"""
    def __init__(self, start):
        self.start = start
    
    def __iter__(self):
        # 返回迭代器对象(这里是self)
        return self
    
    def __next__(self):
        if self.start <= 0:
            # 停止迭代
            raise StopIteration
        
        self.start -= 1
        return self.start + 1

# 使用自定义迭代器
for i in Countdown(5):
    print(i)  # 输出: 5, 4, 3, 2, 1

迭代器与生成器的关系

生成器是一种特殊的迭代器,自动实现了__iter____next__方法:

python 复制代码
# 使用生成器函数创建迭代器
def countdown(start):
    while start > 0:
        yield start
        start -= 1

# 使用生成器创建的迭代器
for i in countdown(5):
    print(i)  # 输出: 5, 4, 3, 2, 1

5. 上下文管理器(Context Managers)

上下文管理器用于管理资源的获取和释放,通常与with语句一起使用。

使用类创建上下文管理器

python 复制代码
class FileManager:
    """文件管理上下文管理器"""
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        """进入上下文时调用"""
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时调用"""
        if self.file:
            self.file.close()
        # 返回True表示异常已处理,False表示异常需要传播
        return False

# 使用自定义上下文管理器
with FileManager('example.txt', 'w') as f:
    f.write('Hello, World!')
# 文件自动关闭

使用contextlib创建上下文管理器

python 复制代码
from contextlib import contextmanager

@contextmanager
def open_file(filename, mode):
    """使用装饰器创建文件管理上下文管理器"""
    try:
        f = open(filename, mode)
        yield f
    finally:
        f.close()

# 使用contextlib创建的上下文管理器
with open_file('example.txt', 'r') as f:
    content = f.read()
    print(content)

多个上下文管理器

python 复制代码
# 同时使用多个上下文管理器
with open('input.txt', 'r') as in_file, open('output.txt', 'w') as out_file:
    content = in_file.read()
    out_file.write(content.upper())

6. 函数式编程

Python支持函数式编程范式,提供了许多函数式编程的特性。

lambda表达式

python 复制代码
# 使用lambda创建匿名函数
add = lambda x, y: x + y
print(add(5, 3))  # 输出: 8

# 在排序中使用lambda
people = [
    {'name': '张三', 'age': 30},
    {'name': '李四', 'age': 25},
    {'name': '王五', 'age': 35}
]

# 按年龄排序
people.sort(key=lambda person: person['age'])
print(people)

map, filter, reduce

python 复制代码
# map: 对可迭代对象的每个元素应用函数
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares)  # 输出: [1, 4, 9, 16, 25]

# filter: 过滤可迭代对象中的元素
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出: [2, 4]

# reduce: 将可迭代对象中的元素累积到单个值
from functools import reduce
product = reduce(lambda x, y: x * y, numbers)
print(product)  # 输出: 120 (1*2*3*4*5)

列表推导式、字典推导式和集合推导式

python 复制代码
# 列表推导式
squares = [x**2 for x in range(10)]
print(squares)  # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # 输出: [0, 4, 16, 36, 64]

# 字典推导式
square_dict = {x: x**2 for x in range(5)}
print(square_dict)  # 输出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 集合推导式
square_set = {x**2 for x in range(5)}
print(square_set)  # 输出: {0, 1, 4, 9, 16}

高阶函数

python 复制代码
# 函数作为参数
def apply_operation(x, y, operation):
    return operation(x, y)

result = apply_operation(5, 3, lambda x, y: x + y)
print(result)  # 输出: 8

# 函数返回函数
def create_multiplier(factor):
    def multiplier(x):
        return x * factor
    return multiplier

double = create_multiplier(2)
triple = create_multiplier(3)

print(double(5))  # 输出: 10
print(triple(5))  # 输出: 15

7. 元类(Metaclasses)

元类是创建类的类,可以用来控制类的创建过程。

基本元类

python 复制代码
# 定义元类
class Meta(type):
    def __new__(mcs, name, bases, attrs):
        # 在类创建前修改类属性
        attrs['added_by_meta'] = '我是由元类添加的属性'
        print(f"创建类: {name}")
        return super().__new__(mcs, name, bases, attrs)

# 使用元类
class MyClass(metaclass=Meta):
    pass

# 实例化类
obj = MyClass()
print(obj.added_by_meta)  # 输出: 我是由元类添加的属性

单例模式实现

python 复制代码
class Singleton(type):
    """单例模式元类"""
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

# 使用单例元类
class Database(metaclass=Singleton):
    def __init__(self):
        print("数据库连接已创建")

# 测试单例
db1 = Database()  # 输出: 数据库连接已创建
db2 = Database()  # 没有输出,因为使用了相同的实例
print(db1 is db2)  # 输出: True

8. 描述符(Descriptors)

描述符是实现了__get____set____delete__方法的对象,用于自定义属性的访问行为。

基本描述符

python 复制代码
class Validator:
    """验证属性值的描述符"""
    def __init__(self, min_value=None, max_value=None):
        self.min_value = min_value
        self.max_value = max_value
        self.name = None
    
    def __set_name__(self, owner, name):
        self.name = name
    
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)
    
    def __set__(self, instance, value):
        if self.min_value is not None and value < self.min_value:
            raise ValueError(f"{self.name}不能小于{self.min_value}")
        if self.max_value is not None and value > self.max_value:
            raise ValueError(f"{self.name}不能大于{self.max_value}")
        instance.__dict__[self.name] = value

# 使用描述符
class Person:
    age = Validator(min_value=0, max_value=120)
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 测试描述符
person = Person("张三", 30)
print(person.age)  # 输出: 30

try:
    person.age = -5  # 引发ValueError
except ValueError as e:
    print(e)  # 输出: age不能小于0

9. 协程(Coroutines)与异步编程

Python 3.5+引入了async/await语法,支持异步编程。

基本协程

python 复制代码
import asyncio

async def say_after(delay, what):
    """等待指定时间后打印消息"""
    await asyncio.sleep(delay)
    print(what)

async def main():
    # 并发运行两个协程
    task1 = asyncio.create_task(say_after(1, '你好'))
    task2 = asyncio.create_task(say_after(2, 'Python'))
    
    print('开始')
    
    # 等待两个任务完成
    await task1
    await task2
    
    print('结束')

# 运行协程
asyncio.run(main())

异步上下文管理器

python 复制代码
import asyncio

class AsyncContextManager:
    async def __aenter__(self):
        print("进入异步上下文")
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("退出异步上下文")
        return False

async def main():
    async with AsyncContextManager() as manager:
        print("在异步上下文中")

asyncio.run(main())

异步生成器

python 复制代码
import asyncio

async def async_generator():
    for i in range(5):
        await asyncio.sleep(0.1)
        yield i

async def main():
    async for i in async_generator():
        print(i)

asyncio.run(main())

10. 函数注解与类型提示

Python 3.5+引入了类型提示,可以提高代码的可读性和可维护性。

基本类型提示

python 复制代码
def add(a: int, b: int) -> int:
    """将两个整数相加"""
    return a + b

def greet(name: str) -> str:
    """向指定的人问候"""
    return f"你好,{name}!"

def process_items(items: list[int]) -> list[int]:
    """处理整数列表"""
    return [item * 2 for item in items]

使用typing模块

python 复制代码
from typing import List, Dict, Tuple, Optional, Union, Callable

# 复杂类型提示
def process_data(
    items: List[int],
    mapping: Dict[str, int],
    config: Optional[Dict[str, str]] = None
) -> Tuple[List[int], int]:
    """处理数据并返回结果元组"""
    if config is None:
        config = {}
    
    result = [item * mapping.get(config.get('factor_key', 'default'), 1) for item in items]
    total = sum(result)
    return result, total

# 函数类型
def apply_function(func: Callable[[int, int], int], x: int, y: int) -> int:
    """应用函数到两个整数"""
    return func(x, y)

类型检查

使用mypy等工具可以进行静态类型检查:

bash 复制代码
# 安装mypy
pip install mypy

# 运行类型检查
mypy your_script.py

11. 练习:高级特性应用

练习1:使用装饰器实现缓存

python 复制代码
import time
from functools import wraps

def memoize(func):
    """缓存函数结果的装饰器"""
    cache = {}
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 创建可哈希的键
        key = str(args) + str(sorted(kwargs.items()))
        
        if key not in cache:
            cache[key] = func(*args, **kwargs)
        return cache[key]
    
    return wrapper

@memoize
def fibonacci(n):
    """计算斐波那契数列的第n个数"""
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 测试缓存效果
start = time.time()
result = fibonacci(35)
end = time.time()
print(f"结果: {result}")
print(f"第一次计算时间: {end - start:.6f} 秒")

start = time.time()
result = fibonacci(35)  # 应该从缓存中获取
end = time.time()
print(f"结果: {result}")
print(f"第二次计算时间: {end - start:.6f} 秒")

练习2:使用生成器处理大文件

python 复制代码
def find_lines_with_pattern(file_path, pattern):
    """在大文件中查找包含指定模式的行"""
    import re
    pattern_regex = re.compile(pattern)
    
    with open(file_path, 'r', encoding='utf-8') as file:
        for line_num, line in enumerate(file, 1):
            if pattern_regex.search(line):
                yield line_num, line.strip()

def process_large_file(file_path, pattern):
    """处理大文件并打印匹配行"""
    print(f"在文件 {file_path} 中查找模式 '{pattern}':")
    
    for line_num, line in find_lines_with_pattern(file_path, pattern):
        print(f"行 {line_num}: {line}")

# 使用示例
# process_large_file('large_log_file.txt', 'ERROR')

12. 今日总结

  • 装饰器允许您修改函数或类的行为,而不需要直接修改其源代码
  • 生成器是一种特殊的迭代器,可以按需生成值,节省内存
  • 迭代器是实现了__iter____next__方法的对象,可以被用于for循环
  • 上下文管理器用于管理资源的获取和释放,通常与with语句一起使用
  • Python支持函数式编程范式,提供了lambda表达式、高阶函数等特性
  • 元类是创建类的类,可以用来控制类的创建过程
  • 描述符用于自定义属性的访问行为
  • Python 3.5+引入了async/await语法,支持异步编程
  • 类型提示可以提高代码的可读性和可维护性

13. 第一周总结

恭喜您完成了Python学习的第一周!在这一周中,我们从Python基础入门开始,逐步学习了Python的数据结构、控制流、函数、面向对象编程、模块与包、文件操作与异常处理,最后是Python的高级特性。

您已经掌握了Python的核心概念和特性,为下一周的学习打下了坚实的基础。在第二周,我们将深入探讨Python的实际应用,包括Web开发、数据处理、测试与调试等方面,帮助您将Python知识应用到实际项目中。

明天我们将开始第二周的学习,首先介绍Python的Web开发框架Flask,帮助您快速构建Web应用。

相关推荐
回家路上绕了弯19 分钟前
深度理解 volatile 与 synchronized:并发编程的两把钥匙
java·后端
程序员清风19 分钟前
ThreadLocal在什么情况下会导OOM?
java·后端·面试
就是帅我不改26 分钟前
基于领域事件驱动的微服务架构设计与实践
后端·面试·架构
JohnYan27 分钟前
Bun技术评估 - 25 Utils(实用工具)
javascript·后端·bun
我要成为Java糕手1 小时前
支付宝芝麻免押支付集成指南及技术对接验收(Java版)
javascript·后端
anthem371 小时前
3、Python持续集成与部署
后端
用户4099322502121 小时前
如何让你的FastAPI Celery Worker在压力下优雅起舞?
后端·github·trae
anthem371 小时前
5、Python文档生成与API设计
后端
ruokkk1 小时前
当你配置了feign.sentinel.enable=true时发生什么
后端·架构