设为首页 加入收藏

TOP

函数的特殊使用方式(二)
2023-07-25 21:28:54 】 浏览:85
Tags:方式
;> int('10010', **kw)
当传入:
>>> max2 = functools.partial(max, 10)
实际上会把10作为args的一部分自动加到左边,也就是:
>>> max2(5, 6, 7)
相当于:
>>> args = (10, 5, 6, 7)
>>> max(
args)

10

当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

5.4.4 闭包

闭包就是一种函数的嵌套,首先定义了一个函数,称之为外部函数。在这个外部函数体中又定义了一个内部函数,并且这个内部函数体中使用到了外部函数的变量。外部函数最后return了内部函数。那么这个外部函数以及内部函数就构成了一个特殊的对象,称之为闭包。
闭包避免了使用全局变量,使得局部变量在函数外被访问成为可能,相比较面向对象,不用继承那么多的额外方法,闭包占用了更少的空间。
闭包示例

a = 1


def out_fun(b):
    c = 3

    def in_fun(d):
        print(a + b + c + d)

    return in_fun


infun = out_fun(2)
infun(4)

10

可以看到,在内部函数in_fun中访问到了全局变量a、外部函数out_fun的局部变量c以及参数b。

5.4.4.2 装饰器

装饰器(decorator)的本质:函数闭包(function closure)的语法糖(Syntactic sugar)。通过给函数装饰,可以加强函数的功能或者增加原本函数没有的功能。
装饰器在第一次调用被装饰函数时进行增强,并且只增强一次。
让我们先从一个简单的函数开始吧。假设现在有一个函数,用来计算从1到100累加之和,并输出结果。为了避免计算太快,我们在使用循环累加时设置等待0.01秒,函数定义如下:

def mysum1():
    from time import sleep
    total = 0
    for _ in range(101):
        sleep(0.01)
        total += _
    print(total)

mysum1()

5050

此时,如果我们想要知道调用这个函数执行一共花了多少时间,我们可以在执行前后获取时间再经过计算得到,也可以通过改造函数,在函数内部函数体前后获取时间计算得到。但是这两种方法都比较麻烦,尤其是第二种方法,需要侵入式修改函数代码。
这个时候就可以通过为函数添加装饰器来实现了。下面是创建装饰器的一般方法:
装饰器的简单定义

def decorator1(func):

    def inner():
        print('在这里执行被装饰函数执行前的增强操作')

        func()  # 执行被装饰的函数

        print('在这里执行被装饰函数执行前的增强操作')

    return inner

从上面可以看出,装饰器也是一个函数。只不过装饰器接收的参数是被装饰的函数。然后再装饰器内部定义一个函数,该内部函数体中执行要增强的操作代码以及执行被装饰的函数。最后再return该内部函数。
接下来是用装饰器来对某个函数进行装饰。我们以上面定义的mysum1函数来进行装饰:
装饰器的使用

@decorator1
def mysum1():
    from time import sleep
    total = 0
    for _ in range(101):
        sleep(0.01)
        total += _
    print(total)
mysum1()

在这里执行被装饰函数执行前的增强操作
5050
在这里执行被装饰函数执行前的增强操作

由上面可以看出,如果要装饰某个函数,只需要在定义这个函数时,在def语句的上一行添加@装饰器函数即可。
对于装饰器装饰一个函数:

@decorator
def myfun():
    print("hello")

上面的代码等价于:

def myfun():
    print("hello")
   
myfun = decorator(myfun)

当一个装饰器装饰函数时,函数的功能增强了,因为在调用这个函数时,实际上调用的是在定义装饰器函数时,其内部函数。而此时内部函数是由增强功能命令和原被装饰函数组成。
创建一个统计函数运行时长的装饰器

import time


def decorator1(func):
    def inner():
        begin = time.time()

        func()  # 执行被装饰的函数

        end = time.time()
        print(f"函数`{func.__name__}`运行的总时间为:{end - begin:.3} 秒")

    return inner


@decorator1
def mysum1():
    from time import sleep
    total = 0
    for _ in range(101):
        sleep(0.01)
        total += _
    print(total)


mysum1()

5050
函数mysum1运行的总时间为:1.59 秒

5.4.4.2.2 被装饰函数接收参数

在上面的例子中,通过装饰器函数decorator装饰的函数是不能有输入参数的,在实际使用中并不是很方便。
通过对装饰器进行改造可以避免这种情况,从而使装饰器函数有更广泛的用途。
装饰器定义:让被装饰函数接收参数

import time


def decorator2(func):
    def inner(*args, **kwargs):
        begin = time.time()

        func(*args, **kwargs)  # 执行被装饰的函数

        end = time.time()
        print(f"函数`{func.__name__}`运行的总时间为:{end - begin:.3}")

    return inner

需要改造的地方:
1、为装饰器函数decorator的内部函数inner在定义时增加收集位置形参和收集关键字形参
2、在装饰器函数decorator的内部函数inner函数体中,执行被装饰器装饰的函数func时,通过参数解包的方式传入参数。
装饰带有参数的函数:

@decorator2
def mysum2(a, b):
    from time import sleep
    total = a
    for _ in range(total + 1, b + 1):
        sleep(0.01)
        total += _
    print(total)


mysum2(1, 100)

5050
函数mysum1运行的总时间为:1.56

5.4.4.2.3 装饰器函数接收参数

通过上面对装饰器进行改造,可以使的被装饰的函数可以输入参数。上面的装饰器函数decorator2可以计算被装饰的函数执行时间,但是只能获取到执行一次的时间。如果想要通过参数获取执行任一次的时间,则需要使得装饰器可以接收参数。
装饰器定义:装饰器接收参数

import time


def decorator3(n):
    def inner(func):
        def wrapper(*args, **kwargs):
            begin = time.time()
            for _ in range(iteration):
                func(*args,
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python unittest+ddt+openpyxl 下一篇【K哥爬虫普法】大数据风控第一案..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目