高级函数¶

高级函数概述¶

在Python中,高级函数是指那些可以接收函数作为参数或返回值为函数的函数。它们可以实现更灵活和强大的功能。常见的高级函数包括高阶函数、装饰器、闭包、生成器等。

1. 高阶函数¶

高阶函数是可以接受函数作为参数或者返回一个函数的函数。

In [1]:
# 例子:使用高阶函数
def apply_function(func, value):
    return func(value)

# 定义一个简单的函数
def square(x):
    return x * x

# 使用高阶函数 apply_function
result = apply_function(square, 5)
print(f'5 的平方是:{result}')
5 的平方是:25

在这个例子中,apply_function是一个高阶函数,它接受另一个函数func作为参数。我们传入函数square和数值5,得到了5的平方结果。

2. 装饰器¶

什么是装饰器? 装饰器是一个特殊的函数,用于“包装”其他函数,以便在不修改原函数代码的情况下,扩展或增强该函数的功能。装饰器函数会在执行原函数之前或之后增加一些操作,或者改变函数的行为。

假设我们有一个函数,它简单地打印一条问候语:

In [ ]:
def say_hello():
    print("Hello!")

如果我们想在打印"Hello!"之前先打印"Start of function",并在之后打印"End of function",我们可以用装饰器来做到这一点。

基本装饰器的结构

一个简单的装饰器是一个包含内部函数的函数。装饰器接收一个函数作为参数,并返回一个新的函数。

In [6]:
# 例子:使用装饰器
def my_decorator(func):
    def wrapper():
        print("Start of function")
        func()
        print("End of function")
    return wrapper

解释:

  • my_decorator是一个装饰器函数,它接收一个函数func作为参数。
  • 在my_decorator内部定义了一个wrapper函数,wrapper会在调用func前后打印额外信息。
  • 最后,my_decorator返回wrapper,这样当我们调用被装饰的函数时,就会先执行wrapper中的内容。

使用装饰器

我们可以用@装饰器名称的方式,把装饰器应用到一个函数上。

In [7]:
@my_decorator
def say_hello():
    print("Hello!")

# 调用函数
say_hello()
Start of function
Hello!
End of function

这里,@my_decorator的作用相当于say_hello = my_decorator(say_hello),即用装饰器函数包装say_hello函数,使得say_hello在执行时自动带上wrapper中的内容。

装饰器的作用

  • 代码复用:可以在多个函数上添加相同的功能,比如记录日志、检查权限等。
  • 增强函数:在不修改原函数代码的情况下扩展其功能,保持代码清晰简洁。

装饰器是用于“包装”函数的工具,适合在不修改原代码的情况下给函数添加功能。初学者可以用装饰器来增加代码的复用性和模块化,提高代码的可读性。

3. 闭包¶

什么是闭包? 在Python中,闭包是一种函数,它可以“记住”在它被定义时所在的作用域,即使这个作用域已经结束了。

闭包是指一个函数在其外部函数作用域内引用了一个变量并且该外部函数已经返回的情况。

闭包的三个关键条件

  • 嵌套函数:闭包是包含在另一个函数内部的函数。

  • 自由变量:内部函数使用外部函数的变量,这些变量称为“自由变量”。

  • 外部函数的返回值是内部函数:外部函数返回这个内部函数,从而形成闭包。

In [4]:
def outer_function(x):
    def inner_function(y):
        return x + y  # 这里,x是自由变量
    return inner_function

outer_function是外部函数,它有一个参数x。

在outer_function内部,定义了另一个函数inner_function,这个内部函数可以使用外部函数outer_function的变量x。

最后,outer_function返回了inner_function。

使用闭包

通过闭包,Python会“记住”在outer_function中传入的变量,即使outer_function结束了。

In [5]:
# 创建一个闭包实例
add_five = outer_function(5)

# 使用闭包
result = add_five(3)  # result = 5 + 3 = 8
print(result)  # 输出 8
8

在这个例子中,add_five是一个闭包,它“记住”了outer_function中x=5的值。即使outer_function已经结束,add_five依然可以使用这个x值并把它和传入的参数y相加。

为什么学习闭包?

闭包可以让我们创建带有内部状态的函数,避免使用全局变量,方便进行数据的保护和模块化的编程。

4. 生成器¶

什么是生成器?

生成器是一种特殊的函数,用于逐步产生一系列值,而不是一次性返回所有的值。生成器可以帮助节省内存,因为它只在需要时才生成数据,而不是将所有数据一次性存储在内存中。生成器用关键字yield代替return,使函数返回一个可迭代的对象。

普通函数 vs. 生成器

一个普通函数在调用后会一次性返回所有结果,函数执行完毕后就结束了。而生成器函数可以暂停,并在每次调用时继续执行,它每次会“产出”一个值并暂停在yield处,直到再次调用时继续产出下一个值。

创建生成器的例子

假设我们想生成一个从1到5的数字序列,我们可以使用生成器来实现:

In [8]:
def count_up_to_five():
    for i in range(1, 6):
        yield i

解释:

这里,count_up_to_five是一个生成器函数。

yield关键字会使函数在每次循环时产出一个值,并暂停在这个位置,等待下次调用时再继续。

使用生成器

当我们调用生成器时,返回的是一个生成器对象,我们可以使用for循环来遍历生成器产生的值。

In [9]:
# 获取生成器对象
gen = count_up_to_five()

# 使用for循环取出生成器的值
for number in gen:
    print(number)
1
2
3
4
5

在每次循环中,生成器只产生一个值,这样可以节省内存,尤其在生成大量数据时非常有用。

生成器的好处

生成器的主要优点在于节省内存和按需生成数据。对于生成大量数据的任务,生成器可以逐步产出数据,而不必将所有数据存储在内存中。

In [10]:
# 例子:使用生成器
def fibonacci_sequence(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

# 使用生成器生成前10个斐波那契数
for number in fibonacci_sequence(10):
    print(number, end=' ')
0 1 1 2 3 5 8 13 21 34 

在这个例子中,fibonacci_sequence是一个生成器函数,它生成斐波那契数列。每次调用yield都会返回一个值,并在下次迭代时继续执行。这种方式非常节省内存,适合处理大量数据。

练习¶

  1. 定义一个高阶函数operate,它接受一个函数和两个数字作为参数,返回该函数作用于这两个数字的结果。
  2. 创建一个装饰器timer_decorator,用于计算函数运行的时间。
  3. 定义一个闭包函数make_multiplier,接受一个参数n,返回一个将数字乘以n的函数。
  4. 使用生成器编写一个函数even_numbers,生成从0开始的前n个偶数。

练习参考答案¶

In [11]:
# 练习 1: 高阶函数操作
def operate(func, x, y):
    return func(x, y)

# 定义一个简单函数用于测试
def add(a, b):
    return a + b

result = operate(add, 10, 5)
print(f'10 和 5 的和是:{result}')
10 和 5 的和是:15
In [12]:
# 练习 2: 计时装饰器
import time

def timer_decorator(func):
    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_decorator
def sample_task(duration):
    time.sleep(duration)

sample_task(1)
函数 sample_task 运行时间:1.003605 秒
In [13]:
# 练习 3: 闭包乘法器
def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

times_three = make_multiplier(3)
print(f'5 乘以 3 是:{times_three(5)}')
5 乘以 3 是:15
In [14]:
# 练习 4: 生成偶数
def even_numbers(n):
    num = 0
    for _ in range(n):
        yield num
        num += 2

for even in even_numbers(5):
    print(even, end=' ')
0 2 4 6 8 
In [ ]: