Python——函数(下)

一.高阶函数

1.定义:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

# 参数为函数
def fun():
    print('Life is short. You need Python.')


def fun1(fun):
    fun()


fun1(fun)
# Life is short. You need Python.

# 返回值为函数
def fun():
    def fun1():
        print('Life is short. You need Python.')

    return fun1()


fun()
# Life is short. You need Python.

2.应用:

  • 例:用函数的方法筛选偶数
# 方法一:普通函数法
def even_numbers(list_0):
    list = []
    for i in list_0:
        if i % 2 == 0:
            list.append(i)
    return list


list = [1, 2, 3,4, 5, 6, 7, 8, 9, 10]
list1 = even_numbers(list)
print(list1)
# [2, 4, 6, 8, 10]

# 方法二:高阶函数法(接受一个或多个函数作为参数)
def even_numbers(fun, list_0):  # 将偶数加入新列表,并将其返回
    list = []
    for i in list_0:
        if fun(i):
            list.append(i)
    return list


def even_number(num):  # 单独判断数字是否为偶数
    if num % 2 == 0:
        return True
    return False


list = [1, 2, 3,4, 5, 6, 7, 8, 9, 10]
list1 = even_numbers(even_number, list)
print(list1)

二.匿名函数——lambda函数

1.定义:匿名函数是指一类无需定义标识符(函数名)的函数或子程序。
lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值
2.接受形式:

函数形式意义
lambda x,y : x+y输入x与y,输出x+y
lambda x:“yes” if 条件 else “no”输入x,若满足条件则输出yes, 否则输出no

3.应用

  • 任意两个数的和
r = lambda a, b: a+b
x = r(1, 2)
print(x)

  • 统计偶数(高阶函数法)
def even_numbers(fun, list_0):  # 将偶数加入新列表,并将其返回
    list_2 = []
    for i in list_0:
        if fun(i):
            list.append(i)
    return list_2


list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
r = lambda x: True if x % 2 == 0 else False  # 将判断函数以匿名函数形式命名
list1 = even_numbers(r, list)
print(list1)

三.闭包

1.定义:

  • 将函数作为返回值也是高阶函数我们也称为闭包
  • 闭包的好处
    • 通过闭包可以创建一些只有当前函数能访问的变量
    • 可以将一些私有数据藏到闭包中
  • 行成闭包的条件
    • 函数嵌套
    • 将内部函数作为返回值返回
    • 内部函数必须要使用到外部函数的变量

2.闭包的特点:

  • 变量不被销毁:函数在运行结束后变量会被销毁掉。如果我们想要将数据保存起来,则需要使用闭包:
def func(num1):
    def func_in(num2):     # 函数嵌套
        x = num1 + num2  # 外层参数调用
        print(x)

    return func_in         # 将内部函数作为返回值返回
    

f = func(1)      # 给num1传一个1
f(2)             # 函数调用,给num2传一个2
  • 变量不可被更改
def func(num1):
    def func_in(num2):     # 函数嵌套
        num1 = 2
        x = num1 + num2  # 外层参数调用
        print(x)

    print(num1)         # 观察num1变化
    func_in(1)
    print(num1)

    return func_in


func(1)
# 1
# 3
# 1
  • 闭包中让外部变量可以修改:
def func(num1):
    def func_in(num2):     # 函数嵌套
        nonlocal num1      # 重新将num1赋值
        num1 = 2
        x = num1 + num2    # 外层参数调用
        print(x)

    print(num1)            # 观察num1变化
    func_in(1)
    print(num1)

    return func_in


func(1)
# 1
# 3
# 2

四.装饰器的引入

1.装饰器的用途:

  • 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
    • 如果修改的函数多,修改起来会比较麻烦
    • 不方便后期的维护
    • 这样做会违反开闭原则(ocp)
    • 程序的设计,要求开发对程序的扩展,要关闭对程序的修改

2.应用

  • 装饰fun1()函数
def fun1():
    print('我是fun1函数')


def fun():
    print('函数开始执行')
    fun1()
    print('函数执行完毕')

# 函数开始执行
# 我是fun1函数
# 函数执行完毕
  • 这样使用装饰器并不能带来更多的简洁,所以我们需要通用装饰器
def fun1():
    print('我是fun1函数')


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


def fun(fn, *args, **kwargs):
    print('函数开始执行')
    r = fn(*args, **kwargs)
    print(r)
    print('函数执行完毕')


fun(add, 1, 2)
fun(fun1)
# 函数开始执行
# 3
# 函数执行完毕

# 函数开始执行
# 我是fun1函数
# None
# 函数执行完毕

五.装饰器的使用

1.装饰器的好处:

  • 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
  • 在开发中,我们都是通过装饰器来扩展函数的功能的

2.如果每次需要装饰函数的时候,都得重新修改,很是麻烦,所以还要引入@的用法。
【拓展】语法糖:(更多内容详查:Python语法糖系列

语法糖(Syntactic sugar):
计算机语言中特殊的某种语法
这种语法对语言的功能并没有影响
对于程序员有更好的易用性
能够增加程序的可读性

  • 简而言之,语法糖就是程序语言中提供[奇技淫巧]的一种手段和方式而已。 通过这类方式编写出来的代码,即好看又好用,好似糖一般的语法。固美其名曰:语法糖
# 通用装饰器
def fun_out(fn, *args, **kwargs):

    def fun_inner(*args, **kwargs):
        print('函数开始执行')
        r = fn(*args, **kwargs)
        print(r)
        print('函数执行完毕')

    return fun_inner


# 需要被装饰的函数
@fun_out            # 等价于 f=fun_out(fun)
def add(a, b):
    return a + b

# 函数开始执行
# 3
# 函数执行完毕

六.应用练习

  1. 请使用装饰器实现已存在的函数的执行所花费的时间。
import time


def timer(program):

    def fun_inner(num, *args, **kwargs):
        print('程序开始')
        start_time = time.time()
        r = program(num)
        print(r)
        end_time = time.time()
        print('程序结束')
        print('耗时:', end_time - start_time)


    return fun_inner


@timer
def program(num):
    s = 0
    for i in range(num):
        s += i
    return s


program(10000000)
# 程序开始
# 49999995000000
# 程序结束
# 耗时: 1.2097764015197754
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值