• Python中闭包、装饰器的概念


    1.闭包(Closure)的概念:

    内部函数中对enclosing作用域的变量进行引用

     1 passline = 60
     2 def func(val):
     3     print('%x' % id(val))
     4     if val >= passline:
     5         print('pass')
     6     else:
     7         print('faild')
     8 
     9     def in_func():
    10         print(val)
    11 
    12     in_func()
    13     return in_func
    14 
    15 f = func(80)
    16 f() #in_func
    17 print(f.__closure__)

    运行结果:

    5d4ff910
    pass
    80
    80
    (<cell at 0x000001B37C8B6CD8: int object at 0x000000005D4FF910>,)


    按照正常的理解,当执行完func函数后,in_func函数无法使用func函数作用域内的变量val,但是通过上面的代码,可以看到val添加到了in_func的__closure__属性中(in_func的属性__closure__对val变量进行了引用,func执行完成后val没有被释放掉),

    也就是说,在函数闭包中,内部函数中对enclosing作用域的变量进行引用,并将引用变量添加到了内部函数__closure__属性中

    2.装饰器

    所谓装饰器,是用来装饰函数,并且返回一个函数对象

    如以下求和与求平均值的两个方法:

    def my_sum(*args):
        if len(args) == 0:
            return 0
        for item in args:
            if not isinstance(item, int):
                return 0
        return sum(args)
    
    def my_average(*args):
        if len(arg) == 0:
            return 0
        for item in args:
            if not isinstance(item, int):
                return 0
        return sum(args) / len(args)
    
    print(my_sum(1,2,3))
    print(my_average(2,3,4,'1'))

    其中,两个方法中都有相同的一段的容错处理代码: 

    if len(arg) == 0:
            return 0
        for item in arg:
            if not isinstance(item, int):
                return 0

    遵循程序设计的DRY原则,这段代码应该进行封装处理,这时便可引入函数闭包

    def dec(func):
        def in_func(*args):
            if len(args) == 0:
                return 0
            for item in args:
                if not isinstance(item, int):
                    return 0
            return func(*args)
        return in_func
    
    def my_sum(*args):
        return sum(args)
    
    def my_average(*args):
        return sum(args) / len(args)
    
    my_sum=dec(my_sum)
    my_average=dec(my_average)
    
    print(my_sum(1,2,3))
    print(my_average(2,3,4,'1'))

    这样就对重复的代码进行了封装。而装饰器是一种语法糖,简化了代码的编写

    def dec(func):
        print('dec called')
        def in_func(*args):
            if len(args) == 0:
                return 0
            for item in args:
                if not isinstance(item, int):
                    return 0
            return func(*args)
        return in_func
    
    @dec
    def my_sum(*args):
        print('my_sum called')
        return sum(args)
    @dec
    def my_average(*args):
        print('my_average called')
        return sum(args) / len(args)
    
    # my_sum=dec(my_sum)
    # my_average=dec(my_average)
    
    print(my_sum(1,2,3))
    print(my_average(2,3,4,'1'))

    运行结果:

    dec called
    dec called
    my_sum called
    6
    0
    程序执行到@dec时,调用 dec方法,返回in_dec,my_sum方法重新被赋值my_sum=in_dec(被装饰函数指向新的函数)
    所以,装饰器@dec的作用就如同执行这行代码:
    my_sum=dec(my_sum)
  • 相关阅读:
    signal, sigaction,信号集合操作
    how to create view (windows)
    设计模式-单例模式
    clearcase command (windows 常用的几个)
    struts2提交文件时,出现页面重置又无法返回input现象,我没有解决这个问题
    报错如HTTP Status 404
    srm开发(基于ssh)(3)
    报错HTTP Status 500
    编写程序时候莫名出现<property name="dialect">org.hibernate.dialect.FirebirdDialect</property>
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [bean.xml]: Invocation of init method failed; nested exception is
  • 原文地址:https://www.cnblogs.com/liubiao/p/5278335.html
Copyright © 2020-2023  润新知