Python 高级知识 - 第一部分

Python 高级知识 - 第一部分

1. 装饰器 (Decorators)

装饰器 是一种 Python 中强大的工具,允许您在不修改函数或类代码的情况下,动态地扩展或修改其行为。 可以将装饰器理解为一种包装器,它接收一个函数(或其他可调用对象)作为输入,并返回一个新的函数(或其他可调用对象),新的函数在调用原始函数前后,可以执行额外的操作。

函数装饰器

下面是一个函数装饰器的例子,用于记录函数的调用:


def log_calls(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function: {func.__name__} with args: {args} and kwargs: {kwargs}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned: {result}")
        return result
    return wrapper

@log_calls
def add(a, b):
    return a + b

add(5, 3) # 输出函数调用信息
    

这个例子中,log_calls 就是一个装饰器,他接收函数add作为参数,并返回一个新函数wrapper,新函数除了调用原始函数外,还多了记录函数调用信息的功能。@log_calls 语法糖等效于add = log_calls(add)

类装饰器

装饰器不仅可以装饰函数,还可以装饰类。类装饰器可以用于在类创建后修改类的行为,例如添加属性或方法。


def add_attr(cls):
    cls.new_attr = "This is a new attribute"
    return cls

@add_attr
class MyClass:
    def __init__(self, value):
        self.value = value

obj = MyClass(10)
print(obj.new_attr) # 输出 "This is a new attribute"
    

类装饰器 add_attr 给被装饰的类 MyClass 添加了一个新的类属性 new_attr

带参数的装饰器

装饰器本身还可以接受参数,这使得装饰器可以更加灵活。


def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

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

greet("Alice") # 执行三次 greet 函数
    

装饰器 repeat 接受一个参数 num_times,然后返回一个装饰器函数。然后这个装饰器函数会被应用到 greet 函数上,使得 greet 函数执行多次。

2. 生成器 (Generators)

生成器 是一种特殊的函数,它不是一次性返回所有值,而是按需生成值。 这在处理大型数据集或无限序列时非常有用,因为它可以避免将所有数据加载到内存中。

使用 `yield` 关键字

生成器函数使用 yield 关键字来生成值,每当调用生成器的 next() 函数时,生成器函数会从上次 yield 的地方继续执行,直到遇到下一个 yield


def my_generator(n):
    for i in range(n):
        yield i

gen = my_generator(3)
print(next(gen)) # 输出 0
print(next(gen)) # 输出 1
print(next(gen)) # 输出 2
# print(next(gen)) # 抛出 StopIteration 异常
    

在上述代码中,my_generator 函数通过 yield 关键字,每次返回一个值。当没有更多值可生成时,会抛出 StopIteration 异常。

生成器表达式

生成器表达式是一种更简洁的方式来创建生成器,其语法类似于列表推导式,但是使用括号 () 而不是方括号 []


squares = (x**2 for x in range(5))
print(next(squares)) # 输出 0
print(next(squares)) # 输出 1
print(next(squares)) # 输出 4
    

这个例子创建了一个生成器 squares,可以按需生成 0 到 4 的平方。

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

上下文管理器 是一种对象,它定义了在 with 语句中使用时,如何管理资源的上下文。 它可以确保在代码块执行前后,资源被正确地分配和释放,例如文件句柄、数据库连接等。

使用类实现上下文管理器

要使用类实现上下文管理器,你需要定义 __enter____exit__ 方法。__enter__ 方法在 with 代码块开始时被调用,__exit__ 方法在代码块结束时被调用,即使代码块中抛出了异常。


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()

with FileManager("test.txt", "w") as f:
    f.write("Hello, context manager!")
    

这个例子中,FileManager 类实现了上下文管理协议,确保文件在 with 代码块结束后被正确关闭。

使用 `@contextmanager` 装饰器

使用 @contextmanager 装饰器可以更方便地创建上下文管理器,只需使用 yield 关键字。


from contextlib import contextmanager

@contextmanager
def timer():
    start_time = time.time()
    yield
    end_time = time.time()
    print(f"Time taken: {end_time - start_time} seconds")

import time
with timer():
    time.sleep(1) # 模拟一些耗时操作
    print("done")
    

在这个例子中,我们定义了一个 timer 上下文管理器来计算代码块的运行时间。

4. 迭代器 (Iterators) 和可迭代对象 (Iterables)

可迭代对象 是指任何可以用 for 循环进行遍历的对象,例如列表、元组、字符串等。 迭代器 是一个可以记住遍历位置的对象,它实现了迭代器协议,即包含 __iter____next__ 方法。

迭代器协议

可迭代对象通过调用 iter() 方法返回一个迭代器对象,迭代器对象通过 next() 方法逐个返回元素。当没有更多元素时,next() 方法会抛出 StopIteration 异常。


my_list = [1, 2, 3]
my_iterator = iter(my_list)

print(next(my_iterator)) # 输出 1
print(next(my_iterator)) # 输出 2
print(next(my_iterator)) # 输出 3
# print(next(my_iterator)) # 抛出 StopIteration 异常
    

上述代码展示了如何从一个可迭代对象中获得迭代器,然后使用迭代器进行遍历

自定义迭代器

你可以通过实现 __iter____next__ 方法来创建自定义迭代器。


class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

my_list = [10,20,30]
my_iterator = MyIterator(my_list)

for item in my_iterator:
  print(item)
    

上述代码中 MyIterator 是一个自定义迭代器,可以遍历一个数组。

5.函数式编程

函数式编程是编程范式的一种,它将计算视为函数求值的过程,并避免改变状态和使用可变数据。在Python中,可以应用一些函数式编程的概念

Lambda 表达式

lambda 表达式是一种匿名函数,可以在需要函数对象的任何地方使用,lambda 表达式的语法如下:

lambda arguments: expression


add = lambda x, y: x + y
print(add(2, 3)) # Output: 5

    

lambda 表达式通常和高阶函数一起使用

map, filter, reduce 函数

map函数接受一个函数和一个可迭代对象作为参数,将函数应用于可迭代对象的每一个元素。


numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares) # Output: [1, 4, 9, 16, 25]
    

filter函数接受一个函数和一个可迭代对象作为参数,filter函数可以筛选出可迭代对象中满足条件的元素


numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4]
    

reduce函数接受一个函数和一个可迭代对象作为参数,将可迭代对象的元素累积计算,返回最终的结果。


from functools import reduce
numbers = [1, 2, 3, 4, 5]
sum_of_numbers = reduce(lambda x, y: x + y, numbers)
print(sum_of_numbers) # Output: 15
    

这只是 Python 高级知识的冰山一角,后续还会继续补充其他主题,敬请期待!

互动区域

登录后可以点赞此内容

参与互动

登录后可以点赞和评论此内容,与作者互动交流