• python笔记(12)--装饰器和推导式


    内容目录

    • 装饰器
    • 推导式

    内容回顾

    1.函数:

    • 参数

      • def(a1,a2):pass

      • def(a1,a2=None):pass 默认参数推荐用不可变类型,慎用可变类型。

      • def(*args,**kwargs):pass

      • 注意:位置参数 > 关键字参数

      • 面试题:

        • 函数可以做参数【知识点】

          def func(arg):
              arg()
          def show():
              pass
          func(show)
          
        • 函数的参数传递的是什么?【内存地址 = 引用 or 值】

          v = [11,2,33,4]
          
          def func(arg):
              print(id(arg))	#列表内存地址
           
          print(id(v))	#列表内存地址
          func(v)
          
          #其打印的都是列表的内存地址,表示传递的都是内存地址
          
        • *args和**kwargs的作用

    • 返回值

      • 常见数据类型可以返回

      • 函数也可以返回

        def func():
            def inner():
                pass
            return inner
        
        v = func()
        
      • 特殊

        • 默认没返回就是None
        • return 1,2,3 等价于return(1,2,3)
    • 执行函数

      • 函数不被调用,内部代码永远不执行

        def func():
            return i
        func_list = []
        for i in range(10):
            func_list.append(func)
        
        print(i)	# 9
        v1 = func_list[4]()
        v2 = func_list[0]()
        
        func_list = []
        for i in range(10):
            #func_list.append(lamdba:x)	#函数不被调用,内部永远不执行
            func_list.append(lamdba:i)	#函数不被调用,内部永远不执行
        print(func_list)	#10个lambda函数
        
        result = func_list[2]()
        print(result)		#9
        
    • 执行函数时,会新创建一块内存保存自己函数执行的信息 =》闭包

      def base(arg):
          return arg
      
      def func(arg):
          def inner():
              return arg
          return inner
      
      base_list = []
      func_list = []
      
      for i in range(10):
          base_list.append(base)
          func_list.append(func(i))
      
      # 1. base_list 和func_list中分别保存了什么?
      """
      base_list = [base,base,base......]共10个相同的base函数(内存地址)
      func_list = [inner,inner,inner......]共10个不同的inner(内存地址),从第一个i = 0,i = 1.....循环到9的不同inner函数的内存地址
      """
      # 2. 如果循环打印什么?
      for item in base_list:
          v = item()	#执行base函数
          print(v)	#都是9
      for data in func_list:
          v = data()
          print(v)	#0,1,2,3,...9
      

    总结:

    • 传参:位置函数 > 关键字参数
    • 函数不被调用,内部代码永远不执行
    • 每次调用函数时,都会为此次调用开辟一块内存,内存可以保存自己以后想要用的值。
    • 函数是作用域,如果自己作用域中没有,则往上级作用域找。

    2.内置和匿名函数

    • 内置函数
    • 匿名函数

    3.模块

    • getpass
    • random
    • hashlib

    4.重点作业

    #1.看代码分析结果
    func_list = []
    for i in range(10):
        func_list.append(lambda x:x + i)#此时列表中增加了i=0-9的匿名函数
    
    
    for i in range(0,len(func_list)):#i=0-9
        result = func_list[i](i)#重新覆盖列表中原i的值,i重新赋值并做参数传入函数
        print(result)#结果为0,2,4,6....18
        
    #2.看代码分析结果【面试题】
    def f1():
        print("f1")
        return f3()
    
    def f2():
        print("f2")
        return f1
    
    def f3():
        print("f3")
    
    func = f2()		#先算等号右边,f2函数执行,输出"f2"返回值为函数f1,此时  func = f1
    result = func() #等号右边为f1(),函数执行后,输出"f1",返回值
    print(result)
    
    #3.分析代码(闭包和调用)
    def func(name):
        return lambda x: x + name
    
    v1 = func(1)    #形成闭包(lambda x:x+1)
    v2 = func(2)    #形成闭包(lambda x:x+2)
    result1 = v1(100)     #执行闭包函数,x = 100,return返回值为101
    result2 = v2(200)     #执行闭包函数,x = 200,return返回值为202
    print(result1,result2)
    

    内容详细

    1.装饰器

    #######################
    def func(arg):
        def inner():
            arg()
        return inner
    
    def f1():
        print(123)
    
    v1 = func(f1)
    v1()
    
    #######################
    def func(arg):      
        def inner():
            arg()
        return inner
    
    def f1():
        print(123)
        return 666
    
    v1 = func(f1)   #{arg = f1,v1 = inner,函数inner的闭包}
    result = v1()   #v1() = inner(),arg = f1,执行inner()函数,结果为print(123),返回值为None
    print(result)   #结果为123,None
    
    #######################
    def func(arg):      
        def inner():
            return arg()		#后续执行函数arg()时,返回值返回给inner函数
        return inner
    
    def f1():
        print(123)
        return 666
    
    v1 = func(f1)   #{arg = f1,v1 = inner,函数inner的闭包}
    result = v1()   #v1() = inner(),arg = f1,执行inner()函数,结果为print(123),返回值为666
    print(result)   #结果为123,666
    
    #######################
    
    def func(arg):
        def inner():
            return arg()
        return inner
    
    def index():
        print('123')
        return 666
    
    #示例一:
    v1 = index()        #执行index函数,打印'123',并返回666给v1
    
    #示例二:
    v2 = func(index)	#index函数作为参数传入func()函数中执行,返回{arg=index函数}的inner函数闭包赋值给v2
    index = 666		    #index函数重新指向666内存地址,但是v2闭包中的index还是指向原来的index函数
    v3 = v2()#因v2中有闭包,相当于执行函数index()并返回值传给inner函数,inner函数中return接收后赋值给v3。
    print(v3)#所以结果为打印123,666
    
    #示例三:
    v4 = func(index)
    index = v4
    index()
    

    通过以上的例子,得出装饰器最终的状态:

    #第一形态
    def func(arg):
        print("此为index的装饰器")
        def inner():
            print("before")
            v = arg()
            print("after")
            return v
        return inner
    
    def index():
        print('123')
        return 666
    
    index = func(index)
    index()
    
    ##最终形态:注意	@装饰器函数
    def func(arg):
        print("此为index的装饰器")
        def inner():
            print("before")
            v = arg()
            print("after")
            return v
        return inner
    
    #第一步:执行func函数并将index函数作为参数传递,相当于func(index)
    #第二步:将func的返回值重新赋值给下面的函数名。index = func(index)
    @func
    def index():
        print('123')
        return 666
    
    print(index())
    

    装饰器:在不改变原函数内部代码的基础上,在函数执行之前和执行之后自动执行某个功能

    应用:

    import time
    
    def func():
        time.sleep(4)
        print(123)
    
    start_time = time.time()#获取当前时间
    func()
    end_time = time.time()
    time = start_time - end_time
    print(time)
    

    总结:

    • 目的:在不改变原来函数的基础上,再函数执行前后在定义功能

    • 编写装饰器的标准格式:

      #装饰器的编写:
      def x(arg):
          def y():
              ret = arg()
              return ret
          return y
      
      #装饰器的应用:
      @x
      def index():
          pass
      
      @x
      def manager():
          pass
      
      #执行函数,自动触发装饰器
      v = index()
      m = manager()
      print(v,m)
      

    应用场景:

    • 想要为函数扩展功能时,可以选择用装饰器。

    总结:

    • 装饰器的编写格式

      • 装饰器第一层函数return的返回值不加内层函数的括号
      def 外层函数(参数):
          def 内层函数(*args,**kwargs):
              return 参数(*args,**kwargs)
          return 内层函数
      
    • 装饰器应用格式:

      @外层函数
      def index():
          pass
      
      index()
      
    • 问题:为什么要加*args,**kwargs

    2.推导式

    列表推导式(常用,熟记)

    • 基本格式

      '''
      目的:方便的生成一个列表
      格式:
      	v1 = [ i for i in 可迭代对象 ]
      	v2 = [ i for i in 可迭代对象 if 条件 ]    #条件为True,才可进行append
      '''
      v1 = [i for i in 'alec']
      v2 = [i+100 for i in range(10)]
      v3 = [99 if i>5 else 66 for i in range(10)]
      
      def func():
          return 100
      v4 = [func for i in range(10)]
      
      v5 = [ lambda : 100 for i in range(10) ]
      result = v5[9]()
      
      def func():
          return i 
      v6 = [func for i in range(10)]
      result = v6[5]()
      
      v7 = [lambda : i for i in range(10)]
      result = v7[5]()
      
      #新浪微博面试题
      #############第一题################
      val = [lambda x:x*i for i in range(10)]
      #1.请问val是什么结果?
      #2.请问val[0](2)的结果是什么?
      
      #############第二题################
      def num():
          return [lambda x:i*x for i in range(4)]
      #num() -> [函数,函数,函数,函数]
      print ([m(2) for m in num()])#[6,6,6,6]
      #1.看代码分析结果
      
      #############筛 选################
      v8 = [i for i in rang(10) if i>5 ]
      #第一步:计算for i in range(10)
      #第二步:判断条件if i>5
      #第三步:符合判断条件的依次赋值给i,添加进列表
      

    集合推导式(集合特性:去重)

    • 跟列表推导式雷同
    • 仅适用集合的特性
    v1 = {i for i in 'alec'}
    

    字典推导式

    • 跟列表推导式雷同
    • 仅适用于字典的特性
      • key键不可重复
    v1 = { 'k'+str(i):i for i in range(10) }
    

    总结

    • 装饰器(特重点,理解+巩固)

      • 编写格式:双层嵌套函数

      • 应用格式:@外层函数

      • 重点记住:

        @xx		# index = xx(index)
        def index():
            pass
        
        index()		#为加入装饰器的index
        
    • 推导式(常用优化)

    • 模块

      import time
      
      v = time.time()	#获取当前时间
      time.sleep(2)	#时间睡眠2秒
      
  • 相关阅读:
    Heroku
    windows平台
    ORTP编译为静态库的问题
    关于Visual Studio 2013 编译 multi-byte character set MFC程序出现 MSB8031 错误的解决办法
    Windows API 磁盘
    Unity项目苹果提审Mach-O文件大于80M问题解决方法
    Unity加载prefab时调用脚本函数顺序和内存释放问题
    Unity3d中多足怪的物理RagDoll实现
    手游各个系统及UI架构剖析
    手游客户端数据表接入随笔
  • 原文地址:https://www.cnblogs.com/lynlearnde/p/12909409.html
Copyright © 2020-2023  润新知