zoukankan      html  css  js  c++  java
  • Python基础(7)闭包函数、装饰器

    一、闭包函数

    闭包函数:1、函数内部定义函数,成为内部函数,
         2、改内部函数包含对外部作用域,而不是对全局作用域名字的引用
    那么该内部函数成为闭包函数
    #最简单的无参闭包函数
    def func1()
        name='ares'
        def func2()
            print(name)
    #有参和返回值的闭包函数
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper

    二、高阶函数

      1)函数接收的参数是一个函数名
      2)函数的返回值是一个函数名
      3)满足上述条件任意一个,都可称之为高阶函数
    #高阶函数应用1:把函数当做参数传给高阶函数
    import time
    def foo():
        print('from the foo')
    def timmer(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    timmer(foo)
    #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
    #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
    import time
    def foo():
        print('from the foo')
    def timmer(func):
        start_time=time.time()
        return func
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    foo=timmer(foo)
    foo()
    #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
    高阶函数总结
    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能
    三、函数嵌套
    #函数的嵌套定义
    def f1():
        def f2():
            def f3():
                print('from f3')
            print('from f2')
            f3()
        print('from f1')
        f2()
    # print(f1)
    f1()
    '''
    from f1
    from f2
    from f3
    '''

    四、装饰器

    1、定义:
    器即函数
    装饰即修饰,意指为其他函数添加新功能
    装饰器定义:本质就是函数,功能是为其他函数添加新功能
    2、装饰器遵循的原则:开放封闭原则(对扩展是开放的,对源码修改是封闭的)
      即、1)不修改被装饰函数的源代码
        2)为被装饰函数添加新功能后,不修改被装饰函数的调用方式
    3、装饰器,装饰器本质可以是任意可调用对象,被装饰的对象也可以是任意可调用对象,
      装饰器的功能是:在不修改被装饰对象源代码以及调用方式的前提下为期添加新功能
     
    装饰器=高阶函数+函数嵌套+闭包
    基本框架
    #这就是一个实现一个装饰器最基本的架子
     def timer(func):
       def wrapper():
         func()
       return wrapper

    例:

    def deco(fn):
        def wapper():
            fn()
        return wapper
    @deco
    def foo():
        print('what are you 弄啥嘞')
    foo()

    统计一个函数运行时间的装饰器

    import time
    import random
    #装饰器
    def timmer(func):
    # func=index
    def wrapper():
    start_time = time.time()
    func() #index()
    stop_time=time.time()
    print('run time is %s' %(stop_time-start_time))
    return wrapper
    #被装饰函数
    def index():
    time.sleep(random.randrange(1,5))
    print('welecome to index page')

    def home():
    time.sleep(random.randrange(1,3))
    print('welecome to HOME page')

    index=timmer(index) #index=wrapper
    home=timmer(home)

    index() #wrapper()
    home()

    装饰器的语法:在被装饰对象的正上方的单独一行,@装饰器名字,#@timer就等同于index=timmer(index)

    import time
    import random
    #装饰器
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
    #被装饰函数
    @timmer             #index=timmer(index)
    def index():
        time.sleep(random.randrange(1,5))
        print('welecome to index page')
    # @timmer #home=timmer(home)
    # def home():
    #     time.sleep(random.randrange(1,3))
    #     print('welecome to HOME page')
    index() #wrapper()
    # home()

    加多个装饰器:

    #加多个装饰器
    import time
    import random
    #装饰器
    def timmer(func):
        def wrapper():
            start_time = time.time()
            func()
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
    def auth(func):
        def deco():
            name=input('name: ')
            password=input('password: ')
            if name == 'egon' and password == '123':
                print('login successful')
                func() #wrapper()
            else:
                print('login err')
        return deco
    #被装饰函数  #多个装饰函数,从上往下添加,调用时从下往上
    @auth                 #index=auth(wrapper) #index=deco                                   #index=auth(wrapper) #index=deco
    @timmer                #index=timmer(index) #index=wrapper
    def index():
        # time.sleep(random.randrange(1,5))
        time.sleep(3)
        print('welecome to index page')
    def home():
        time.sleep(random.randrange(1,3))
        print('welecome to HOME page')
    # index() #deco()
    # home()

    装饰器修订:

    #装饰器修订
    import time
    import random
    #装饰器
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time = time.time()
            res=func(*args,**kwargs)  #接收参数
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res    #增加返回值
        return wrapper
    #被装饰函数
    @timmer
    def index():
        time.sleep(random.randrange(1,5))
        print('welecome to index page')
    @timmer
    def home(name):
        time.sleep(random.randrange(1,3))
        print('welecome to %s HOME page' %name)
        return 123123123123123123123123123123123123123123
    index()
    res1=index()
    print('index return %s' %res1)
    res2=home('egon') #wraper()
    print('home return %s' %res2)

     扩展:

    """
    python内置装饰器
    在python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod、property.
        @staticmethod 是类的静态方法,其跟成员方法的区别是没有self参数,并且可以在类不进行实例化的情况下调用
        @classmethod 与成员方法的区别在于所接收的第一个参数不是self(类实例的指针),而是cls(当前类的具体类型)
        @property 是属性的意思,表示可以通过类实例直接访问的信息
    """
    
    class Foo(object):
        def __init__(self,var):
            super(Foo,self).__init__()
            self._var=var
    
        @property
        def var(self):
            return self._var
    
        @var.setter
        def var(self,var):
            self._var=var
    
    f=Foo('var1')
    print(f.var)
    f.var='var2'
    print(f.var)
    
    """
    注意,对于Python新式类(new-style class),如果将上面的 “@var.setter” 装饰器所装饰的成员函数去掉,
    则Foo.var 属性为只读属性,使用 “foo.var = ‘var 2′” 进行赋值时会抛出异常。
    但是,对于Python classic class,所声明的属性不是 read-only的,所以即使去掉”@var.setter”装饰器也不会报错。
    """
  • 相关阅读:
    解释 ASP.NET中的Web页面与其隐藏类之间的关系
    B/S与C/S的联系与区别
    三层架构
    列举 ASP.NET页面之间传递值的几种方式
    什么是SQL注入式攻击?如何防范?
    post、get的区别
    Session,ViewState,Application,cookie的区别?
    Vue 09.前后端交互
    Vue 08.webpack中使用.vue组件
    Vue 07.webpack
  • 原文地址:https://www.cnblogs.com/shenbuer/p/7055214.html
Copyright © 2011-2022 走看看