python装饰器详解
发布日期:2021-06-27 12:56:16 浏览次数:51 分类:技术文章

本文共 3431 字,大约阅读时间需要 11 分钟。

一、函数名的运用

函数名是⼀个变量,但它是⼀个特殊的变量。与括号配合可以执⾏函数的变量

1. 做变量

def func():    print('呵呵')a = func  # 把函数当成变量赋值给另外一个变量a()  # 通过变量a调用函数

2. 做容器元素

def func1():    print('func1')def func2():    print('func2')       def func3():    print('func3')          def func4():    print('func4')list1 = [func1, func2, func3, func4]for i in list1:    i()

3. 做参

def func1():    print('func1')def func2(arg):    print('start')    arg()  # 执行传递进来的arg    print('end')func2(func1)  # 把func1当成参数传递给func2

4. 做返回值

def func1():    print('这里是func1')    def func2():        print('这里是func2')    return func2  # 把func2当成返回值返回ret = func1()  # 调用func1,把返回值赋值给retret()  # 调用ret

二、闭包

**1、定义:**一个内层函数中,引用了外层函数(非全局)的变量,这个内层函数就可以成为闭包。在Python中,我们可以使用__closure__来检测函数是否是闭包。

2、例子:

def print_msg(msg): # 这是外层函数    def printer():    # 这是内层函数        print(msg)    return printer   # 返回内层函数func = print_msg("Hello")    #返回printer变量func()          #实际上执行是printer()函数

现在我们进行如下操作:

>>> del print_msg>>> func()Hello>>> print_msg("Hello")Traceback (most recent call last):...NameError: name 'print_msg' is not defined

总结:

如果⼀个函数执⾏完毕,则这个函数中的变量以及局部命名空间中的内容都将会被销毁。在闭包中内部函数会引用外层函数的变量,而且这个变量将不会随着外层函数的结束而销毁,它会在内存中保留。也就是说,闭包函数可以保留其用到的变量的引用。

三、装饰器

1、开放封闭原则是指对扩展代码的功能是开放的,但是对修改源代码是封闭的。这样的软件设计思路可以保证我们更好的开发和维护我们的代码。

2、利用闭包解释装饰器:

def c():    print('11111111')def a(func):    def b():        print('aaaa')        func()    return bc = a(c)  # 运行步骤:a(c)=>func()=c() =>返回值赋值 c=bc()    #实际运行 b()=>打印aaa=>运行c()=>打印1111111

3、装饰器规范写法如下:

def a(func):    def b():        print(1111')        func()    return b@a  # 装饰器语法def c():    print('cccccc!')    # 调用被装饰函数c()

4、带参数的装饰器

def f1(func):  # f1是我们定义的装饰器函数,func是被装饰的函数    def f2(*arg, **kwargs):  # *args和**kwargs是被装饰函数的参数        func(*arg, **kwargs)    return f2

5、装饰器修复技术

**(1)**被装饰的函数最终都会失去本来的__doc__等信息, Python给我们提供了一个修复被装饰函数的工具。在装饰器内部加入 @wraps(func)进行修复
(2)例子

def a(func):    @wraps(func)   #可以将这个除去试试    def b():        print('洒点水')        func()    return b@a  # 装饰器语法糖def create_people():    """这是一个女娲造人的功能函数"""    print('女娲真厉害,捏个泥吹口气就成了人!')create_people()print(create_people.__doc__)print(create_people.__name__)

6、多个装饰器修饰一个函数执行顺序为从下至上

7、类装饰器:
(1)基础知识:__init__和__call__分别为类中的初始函数和直接调用函数,都属于魔法函数(python内置的)
(2)实例:

class D(object):    def __init__(self, a=None):  #初始函数,调用类首先执行这个函数        self.a = a        self.mode = "装饰"    def __call__(self, *args, **kwargs):        if self.mode == "装饰":            self.func = args[0]  # 默认第一个参数是被装饰的函数            self.mode = "调用"            return self        # 当self.mode == "调用"时,执行下面的代码(也就是调用使用类装饰的函数时执行)        if self.a:            print("欢迎来到{}页面。".format(self.a))        else:            print("欢迎来到首页。")        self.func(*args, **kwargs)@D()def index(name):    print("Hello {}.".format(name))    if __name__ == '__main__':    index('张三') #调用时调用类中的__call__函数

8、property属性方法

(1)我们把类中的一个只读属性定义为property属性方法,只有在访问它时才参与计算,一旦访问了该属性,我们就把这个值缓存起来,下次再访问的时候无需重新计算。
(2)例子:

class lazyproperty:    def __init__(self, func):        self.func = func    def __get__(self, instance, owner):        if instance is None:            return self        else:            value = self.func(instance)            setattr(instance, self.func.__name__, value)            return valueimport mathclass Circle:    def __init__(self, radius):        self.radius = radius    @lazyproperty    def area(self):        print('计算面积')        return math.pi * self.radius ** 2c1 = Circle(10)print(c1.area)print(c1.area)#执行这个会发现这一步只返回了值,没有重新执行函数。

转载地址:https://blog.csdn.net/weixin_43458262/article/details/102724638 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:pycharm连接mysql出现时间问题
下一篇:解决无法创建使用pip.exe创建进程

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年02月04日 18时31分09秒