• 第二篇(上)函数


    • 1 函数的基本使用
      复习十五分钟:
          1、编写代码实现功能tail -f access.log
              f.seek()
      
              应用程序(文件对象/文件句柄1)     应用程序(文件对象/文件句柄2)
              操作系统(真正的文件)a.txt z
              计算机硬件(硬盘空间)
      
          2、代码展示文件修改的两种方式
              方式一:
              with open('源文件',mode='r') as src_f:
                  res=src_f.read()
                  new_res=修改res
      
              with open('源文件',mode='w') as dst_f:
                  dst.write(new_res)
      
      
             方式二:
             with open('源文件',mode='r') as src_f,open('临时文件',mode='w') as dst_f:
                  for line in src_f:
                      new_line=修改line
                      dst.write(new_line)
      
             删除源文件
             将临时文件重命名为源文件的名字
      
      
          3、定义函数的语法是什么?
              函数-》盛放功能(一堆代码)的容器
      
              内置函数:python解释已经定义好了,直接调用即可
                  open()
                  input()
              自定义函数:
                  先定义
                  后调用
      
              def 函数名(参数1,参数2,...):
                  """文档注释"""
                  代码块
                  return4、函数的基本使用遵循的原则是?
      
          5、简述函数定义阶段与调用阶段发生的事情
              定义阶段:
                  1、申请内存空间将函数体代码存放起来,然后将内存地址绑定给函数名
                      函数名=函数的内地址
                  2、只检测语法,不执行代码
      
              调用函数:函数名()
                  1、先通过函数名(变量名)找函数的内存
                  2、加括号触发函数体代码的运行
      
          6、代码展示定义函数的三种形式
              def func():
                  pass
              func()
      
              def func(x,y):
                  pass
      
              func(1,2)
      
              def func():
                  pass
      
          7、代码展示调用函数的三种形式
              # 语句形式:只运行功能
              func(1,2)
              func()
      
              # 表达式形式
              res=func(1,2)
      
              res=func(1,2)*10
      
              # 参数传入
              func(func(1,2),10)
          8、return返回值的三种形式是什么?
              None:   没有return
                      return
                      return None
      
              一个值:
                  return 值
      
              多个值
                  return 值1,值2,值3
      
              强调:
                  return是函数结束的标志,函数内可以有多个return,但只要执行一个
                  整个函数就会立刻结束,并且将该return后的值作为本次运行的结果返回
      
      
      上节课复习
      
      今日内容:函数参数的使用
      一 形参与实参介绍
      二 形参与实参的具体使用
      2.1 位置参数
      2.2 关键字参数
      2.3 默认参数
      2.4 可变长度的参数(*与**的用法)
      2.4.1 可变长度的位置参数
      2.4.2 可变长度的关键字参数
      2.5 命名关键字参数(了解)
      2.6 组合使用(了解)
      函数参数的使用.txt
      """
      @作者: egon老湿
      @微信:18611453110
      @专栏: https://zhuanlan.zhihu.com/c_1189883314197168128
      
      1、什么是函数
          函数就相当于具备某一功能的工具
          函数的使用必须遵循一个原则:
              先定义
              后调用
      2、为何要用函数
          1、组织结构不清晰,可读性差
          2、代码冗余
          3、可维护性、扩展性差
      
      3、如何用函数
              先定义
                  三种定义方式
              后调用
                  三种调用方式
      
              返回值
                  三种返回值的形式
      
      """
      # 一、先定义
      # 定义的语法
      '''
      def 函数名(参数1,参数2,...):
          """文档描述"""
          函数体
          return 值
      '''
      
      
      # 形式一:无参函数
      # def func():
      #     # x
      #     # print(
      #     print('哈哈哈')
      #     print('哈哈哈')
      #     print('哈哈哈')
      
      # 定义函数发生的事情
      # 1、申请内存空间保存函数体代码
      # 2、将上述内存地址绑定函数名
      # 3、定义函数不会执行函数体代码,但是会检测函数体语法
      
      # 调用函数发生的事情
      # 1、通过函数名找到函数的内存地址
      # 2、然后加口号就是在触发函数体代码的执行
      # print(func)
      # func()
      
      # 示范1
      # def bar(): # bar=函数的内存地址
      #     print('from bar')
      #
      # def foo():
      #     # print(bar)
      #     bar()
      #     print('from foo')
      #
      # foo()
      
      # 示范2
      # def foo():
      #     # print(bar)
      #     bar()
      #     print('from foo')
      #
      # def bar():  # bar=函数的内存地址
      #     print('from bar')
      #
      # foo()
      
      # 示范3
      # def foo():
      #     # print(bar)
      #     bar()
      #     print('from foo')
      #
      # foo()
      #
      # def bar():  # bar=函数的内存地址
      #     print('from bar')
      
      # 形式二:有参函数
      # def func(x,y): # x=1  y=2
      #     print(x,y)
      # func(1,2)
      
      # 形式三:空函数,函数体代码为pass
      def func(x, y):
          pass
      
      
      # 三种定义方式各用在何处
      # 1、无参函数的应用场景
      # def interactive():
      #     name=input('username>>: ')
      #     age=input('age>>: ')
      #     gender=input('gender>>: ')
      #     msg='名字:{} 年龄:{} 性别'.format(name,age,gender)
      #     print(msg)
      #
      # interactive()
      # interactive()
      # interactive()
      # interactive()
      
      # 2、有参函数的应用场景
      # def add(x,y): # 参数-》原材料
      #     # x=20
      #     # y=30
      #     res=x + y
      #     # print(res)
      #     return res # 返回值-》产品
      #
      # # add(10,2)
      # res=add(20,30)
      # print(res)
      
      # 3、空函数的应用场景
      # def auth_user():
      #     """user authentication function"""
      #     pass
      #
      # def download_file():
      #     """download file function"""
      #     pass
      #
      # def upload_file():
      #     """upload file function"""
      #     pass
      #
      # def ls():
      #     """list contents function"""
      #     pass
      #
      # def cd():
      #     """change directory"""
      #     pass
      
      
      # 二、调用函数
      # 1、语句的形式:只加括号调用函数
      # interactive()
      # add(1,2)
      
      # 2、表达式形式:
      # def add(x,y): # 参数-》原材料
      #     res=x + y
      #     return res # 返回值-》产品
      # 赋值表达式
      # res=add(1,2)
      # print(res)
      # 数学表达式
      # res=add(1,2)*10
      # print(res)
      
      # 3、函数调用可以当做参数
      # res=add(add(1,2),10)
      # print(res)
      
      # 三、函数返回值
      # return是函数结束的标志,即函数体代码一旦运行到return会立刻
      # 终止函数的运行,并且会将return后的值当做本次运行的结果返回:
      # 1、返回None:函数体内没有return
      #             return
      #             return None
      #
      # 2、返回一个值:return 值
      # def func():
      #     return 10
      #
      # res=func()
      # print(res)
      
      # 3、返回多个值:用逗号分隔开多个值,会被return返回成元组
      def func():
          return 10, 'aa', [1, 2]
      
      res = func()
      print(res, type(res))
      
      
      
      # 函数参数的使用
      """
      @作者: egon老湿
      @微信:18611453110
      @专栏: https://zhuanlan.zhihu.com/c_1189883314197168128
      """
      
      
      # 一 形参与实参介绍
      # 形参:在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
      def func(x, y):  # x=1,y=2
          print(x, y)
      
      
      # 实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
      # func(1,2)
      
      # 形参与实参的关系:
      # 1、在调用阶段,实参(变量值)会绑定给形参(变量名)
      # 2、这种绑定关系只能在函数体内使用
      # 3、实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系
      
      # 实参是传入的值,但值可以是以下形式
      # 形式一:
      # func(1,2)
      
      # 形式二:
      # a=1
      # b=2
      # func(a,b)
      
      # 形式三:
      # func(int('1'),2)
      # func(func1(1,2,),func2(2,3),333)
      
      
      # 二 形参与实参的具体使用
      # 2.1 位置参数:按照从左到右的顺序依次定义的参数称之为位置参数
      # 位置形参:在函数定义阶段,按照从左到右的顺序直接定义的"变量名"
      #        特点:必须被传值,多一个不行少一个也不行
      # def func(x,y):
      #     print(x,y)
      # func(1,2,3)
      # func(1,)
      
      # 位置实参:在函数调用阶段, 按照从左到有的顺序依次传入的值
      #        特点:按照顺序与形参一一对应
      
      # func(1,2)
      # func(2,1)
      
      # 2.2 关键字参数
      # 关键字实参:在函数调用阶段,按照key=value的形式传入的值
      #       特点:指名道姓给某个形参传值,可以完全不参照顺序
      # def func(x,y):
      #     print(x,y)
      
      # func(y=2,x=1)
      # func(1,2)
      
      # 混合使用,强调
      # 1、位置实参必须放在关键字实参前
      # func(1,y=2)
      # func(y=2,1)
      
      # 2、不能能为同一个形参重复传值
      # func(1,y=2,x=3)
      # func(1,2,x=3,y=4)
      
      
      # 2.3 默认参数
      # 默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数
      #       特点:在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值
      # def func(x,y=3):
      #     print(x,y)
      #
      # # func(x=1)
      # func(x=1,y=44444)
      
      
      # def register(name,age,gender='男'):
      #     print(name,age,gender)
      #
      # register('三炮',18)
      # register('二炮',19)
      # register('大炮',19)
      # register('没炮',19,'女')
      
      
      # 位置形参与默认形参混用,强调:
      # 1、位置形参必须在默认形参的左边
      # def func(y=2,x):
      #     pass
      
      # 2、默认参数的值是在函数定义阶段被赋值的,准确地说被赋予的是值的内存地址
      # 示范1:
      # m=2
      # def func(x,y=m): # y=>2的内存地址
      #     print(x,y
      # m=3333333333333333333
      # func(1)
      
      # 示范2:
      # m = [111111, ]
      #
      # def func(x, y=m): # y=>[111111, ]的内存地址
      #     print(x, y)
      #
      # m.append(3333333)
      # func(1)
      
      # 3、虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型
      # 函数最理想的状态:函数的调用只跟函数本身有关系,不外界代码的影响
      # m = [111111, ]
      #
      # def func(x, y=m):
      #     print(x, y)
      #
      # m.append(3333333)
      # m.append(444444)
      # m.append(5555)
      #
      #
      # func(1)
      # func(2)
      # func(3)
      
      
      # def func(x,y,z,l=None):
      #     if l is None:
      #         l=[]
      #     l.append(x)
      #     l.append(y)
      #     l.append(z)
      #     print(l)
      
      # func(1,2,3)
      # func(4,5,6)
      
      # new_l=[111,222]
      # func(1,2,3,new_l)
      
      
      # 2.4 可变长度的参数(*与**的用法)
      # 可变长度指的是在调用函数时,传入的值(实参)的个数不固定
      # 而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收
      
      # 2.4.1 可变长度的位置参数
      # I:*形参名:用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值紧跟其后的形参名
      #           *后跟的可以是任意名字,但是约定俗成应该是args
      
      # def func(x,y,*z): # z =(3,4,5,6)
      #     print(x,y,z)
      
      # func(1,2,3,4,5,6)
      
      # def my_sum(*args):
      #     res=0
      #     for item in args:
      #         res+=item
      #     return res
      #
      # res=my_sum(1,2,3,4,)
      # print(res)
      
      # II: *可以用在实参中,实参中带*,先*后的值打散成位置实参
      # def func(x,y,z):
      #     print(x,y,z)
      #
      # # func(*[11,22,33]) # func(11,22,33)
      # # func(*[11,22]) # func(11,22)
      #
      # l=[11,22,33]
      # func(*l)
      
      # III: 形参与实参中都带*
      # def func(x,y,*args): # args=(3,4,5,6)
      #     print(x,y,args)
      
      # func(1,2,[3,4,5,6])
      # func(1,2,*[3,4,5,6]) # func(1,2,3,4,5,6)
      # func(*'hello') # func('h','e','l','l','o')
      
      
      # 2.4.2 可变长度的关键字参数
      # I:**形参名:用来接收溢出的关键字实参,**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参名
      #           **后跟的可以是任意名字,但是约定俗成应该是kwargs
      # def func(x,y,**kwargs):
      #     print(x,y,kwargs)
      #
      # func(1,y=2,a=1,b=2,c=3)
      
      # II: **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参
      # def func(x,y,z):
      #     print(x,y,z)
      
      # func(*{'x':1,'y':2,'z':3}) # func('x','y','z')
      # func(**{'x':1,'y':2,'z':3}) # func(x=1,y=2,z=3)
      
      # 错误
      # func(**{'x':1,'y':2,}) # func(x=1,y=2)
      # func(**{'x':1,'a':2,'z':3}) # func(x=1,a=2,z=3)
      
      
      # III: 形参与实参中都带**
      # def func(x,y,**kwargs):
      #     print(x,y,kwargs)
      
      # func(y=222,x=111,a=333,b=444)
      # func(**{'y':222,'x':111,'a':333,'b':4444})
      
      
      
      
      # 混用*与**:*args必须在**kwargs之前
      # def func(x,*args,**kwargs):
      #     print(args)
      #     print(kwargs)
      #
      # func(1,2,3,4,5,6,7,8,x=1,y=2,z=3)
      
      
      def index(x,y,z):
          print('index=>>> ',x,y,z)
      
      def wrapper(*args,**kwargs): #args=(1,) kwargs={'z':3,'y':2}
          index(*args,**kwargs)
          # index(*(1,),**{'z':3,'y':2})
          # index(1,z=3,y=2)
      
      wrapper(1,z=3,y=2) # 为wrapper传递的参数是给index用的
      # 原格式---》汇总-----》打回原形
      
      
      
      # 2.5 命名关键字参数(了解)
      # 2.6 组合使用(了解)
      函数基本使用&参数使用
        1  1. 命名关键字参数(了解)
        2 #  命名关键字参数:在定义函数时,*后定义的参数,如下所示,称之为命名关键字参数
        3 # 特点:
        4 # 1、命名关键字实参必须按照key=value的形式为其传值
        5 # def func(x,y,*,a,b): # 其中,a和b称之为命名关键字参数
        6 #     print(x,y)
        7 #     print(a,b)
        8 #
        9 # # func(1,2,b=222,a=111)
       10 
       11 # 示例
       12 # def func(x,y,*,a=11111,b):
       13 #     print(x,y)
       14 #     print(a,b)
       15 #
       16 # func(1,2,b=22222)
       17 
       18 # 2. 组合使用(了解)
       19 # 形参混用的顺序:位置新参,默认形参,*args,命名关键字形参,**kwargs
       20 # def func(x,y=111,*args,z,**kwargs):
       21 #     print(x)
       22 #     print(y)
       23 #     print(args)
       24 #     print(z)
       25 #     print(kwargs)
       26 #
       27 
       28 
       29 # 实参混用的顺序:
       30 def func(x,y,z,a,b,c):
       31     print(x)
       32     print(y)
       33     print(z)
       34     print(a)
       35     print(b)
       36     print(c)
       37 
       38 # func(111,y=222,*[333,444],**{'b':555,'c':666})
       39 # func(111,y=222,333,444,b=555,c=666)
       40 
       41 # func(111,*[333,444],a=222,**{'b':555,'c':666})
       42 # func(111,333,444,a=222,b=555,c=66)
       43 
       44 # func(111,*[333,444],**{'b':555,'c':666},a=222,)
       45 func(111,3333,4444,b=555,c=666,a=222)
       46 
       47 
       48 # func(1)
       49 # func(x=1)
       50 # func(1,x=1)
       51 # func(*'hello')
       52 # func(**{})
       53 # func(*'hell',**{})
       54 
       55 
       56 # 名称空间与作用域
       57 # 一:名称空间namespacs:存放名字的地方,是对栈区的划分
       58 # 有了名称空间之后,就可以在栈区中存放相同的名字,详细的,名称空间
       59 # 分为三种
       60 # 1.1 内置名称空间
       61 # 存放的名字:存放的python解释器内置的名字
       62 '''
       63 >>> print
       64 <built-in function print>
       65 >>> input
       66 <built-in function input>
       67 '''
       68 # 存活周期:python解释器启动则产生,python解释器关闭则销毁
       69 
       70 
       71 # 1.2 全局名称空间
       72 # 存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字
       73 # 存活周期:python文件执行则产生,python文件运行完毕后销毁
       74 
       75 # import os
       76 #
       77 # x=10
       78 # if 13 > 3:
       79 #     y=20
       80 #     if 3 == 3:
       81 #         z=30
       82 #
       83 # # func=函数的内存地址
       84 # def func():
       85 #     a=111
       86 #     b=222
       87 
       88 # class Foo:
       89 #     pass
       90 
       91 
       92 
       93 # 1.3 局部名称空间
       94 # 存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
       95 # 存活周期:在调用函数时存活,函数调用完毕后则销毁
       96 # def func(a,b):
       97 #     pass
       98 #
       99 # func(10,1)
      100 # func(11,12)
      101 # func(13,14)
      102 # func(15,16)
      103 
      104 
      105 # 1.4 名称空间的加载顺序
      106 # 内置名称空间>全局名称空间>局部名称空间
      107 
      108 # 1.5 销毁顺序
      109 # 局部名称空间>全局名空间>内置名称空间
      110 
      111 # 1.6 名字的查找优先级:当前所在的位置向上一层一层查找
      112 # 内置名称空间
      113 # 全局名称空间
      114 # 局部名称空间
      115 
      116 # 如果当前在局部名称空间:
      117 # 局部名称空间—>全局名称空间->内置名称空间
      118 # # input=333
      119 #
      120 # def func():
      121 #     # input=444
      122 #     print(input)
      123 #
      124 # func()
      125 
      126 
      127 # 如果当前在全局名称空间
      128 # 全局名称空间->内置名称空间
      129 # input=333
      130 # def func():
      131 #     input=444
      132 # func()
      133 # print(input)
      134 
      135 
      136 # 示范1:
      137 # def func():
      138 #     print(x)
      139 # x=111
      140 #
      141 # func()
      142 
      143 # 示范2:名称空间的"嵌套"关系是以函数定义阶段为准,与调用位置无关
      144 # x=1
      145 # def func():
      146 #    print(x)
      147 #
      148 #
      149 # def foo():
      150 #     x=222
      151 #     func()
      152 #
      153 # foo()
      154 
      155 # 示范3:函数嵌套定义
      156 # input=111
      157 # def f1():
      158 #     def f2():
      159 #         # input=333
      160 #         print(input)
      161 #     input=222
      162 #
      163 #     f2()
      164 #
      165 #
      166 # f1()
      167 
      168 
      169 # 示范4:
      170 # x=111
      171 # def func():
      172 #     print(x) #
      173 #     x=222
      174 #
      175 # func()
      176 
      177 
      178 # 二:作用域-》作用范围
      179 # 全局作用域:内置名称空间、全局名称空间
      180 # 1、全局存活
      181 # 2、全局有效:被所有函数共享
      182 
      183 # x=111
      184 #
      185 # def foo():
      186 #     print(x,id(x))
      187 #
      188 # def bar():
      189 #     print(x,id(x))
      190 #
      191 # foo()
      192 # bar()
      193 
      194 # print(x,id(x))
      195 
      196 # 局部作用域: 局部名称空间的名字
      197 # 1、临时存活
      198 # 2、局部有效:函数内有效
      199 
      200 # def foo(x):
      201 #     def f1():
      202 #         def f2():
      203 #             print(x)
      204 
      205 
      206 
      207 # LEGB
      208 # # builtin
      209 # # global
      210 # def f1():
      211 #     # enclosing
      212 #     def f2():
      213 #         # enclosing
      214 #         def f3():
      215 #             # local
      216 #             pass
      名称空间&作用域
    • 2 函数对象&嵌套&闭包
        1 # 精髓:可以把函数当成变量去用
        2 # func=内存地址
        3 def func():
        4     print('from func')
        5 
        6 
        7 # 1、可以赋值
        8 # f=func
        9 # print(f,func)
       10 # f()
       11 
       12 # 2、可以当做函数当做参数传给另外一个函数
       13 # def foo(x): # x = func的内存地址
       14 #     # print(x)
       15 #     x()
       16 #
       17 # foo(func) # foo(func的内存地址)
       18 
       19 # 3、可以当做函数当做另外一个函数的返回值
       20 # def foo(x): # x=func的内存地址
       21 #     return x # return func的内存地址
       22 #
       23 # res=foo(func) # foo(func的内存地址)
       24 # print(res) # res=func的内存地址
       25 #
       26 # res()
       27 
       28 # 4、可以当做容器类型的一个元素
       29 # l=[func,]
       30 # # print(l)
       31 # l[0]()
       32 
       33 # dic={'k1':func}
       34 # print(dic)
       35 # dic['k1']()
       36 
       37 # 函数对象应用示范:
       38 # def login():
       39 #     print('登录功能')
       40 #
       41 #
       42 # def transfer():
       43 #     print('转账功能')
       44 #
       45 #
       46 # def check_banlance():
       47 #     print('查询余额')
       48 #
       49 # def withdraw():
       50 #     print('提现')
       51 #
       52 #
       53 # def register():
       54 #     print('注册')
       55 #
       56 # func_dic={
       57 #     '1':login,
       58 #     '2':transfer,
       59 #     '3':check_banlance,
       60 #     '4':withdraw,
       61 #     '5':register
       62 # }
       63 #
       64 # # func_dic['1']()
       65 #
       66 #
       67 # while True:
       68 #     print("""
       69 #     0 退出
       70 #     1 登录
       71 #     2 转账
       72 #     3 查询余额
       73 #     4 提现
       74 #     5 注册
       75 #     """)
       76 #     choice = input('请输入命令编号:').strip()
       77 #     if not choice.isdigit():
       78 #         print('必须输入编号,傻叉')
       79 #         continue
       80 #
       81 #     if choice == '0':
       82 #         break
       83 #
       84 #
       85 #     if choice in func_dic:
       86 #         func_dic[choice]()
       87 #     else:
       88 #         print('输入的指令不存在')
       89 #
       90 #     # if choice == '1':
       91 #     #     login()
       92 #     # elif choice == '2':
       93 #     #     transfer()
       94 #     # elif choice == '3':
       95 #     #     check_banlance()
       96 #     # elif choice == '4':
       97 #     #     withdraw()
       98 #     # else:
       99 #     #     print('输入的指令不存在')
      100 
      101 
      102 # 修正
      103 def login():
      104     print('登录功能')
      105 
      106 
      107 def transfer():
      108     print('转账功能')
      109 
      110 
      111 def check_banlance():
      112     print('查询余额')
      113 
      114 
      115 def withdraw():
      116     print('提现')
      函数对象
       1 # 函数嵌套
       2 # 1、函数的嵌套调用:在调用一个函数的过程中又调用其他函数
       3 # def max2(x,y):
       4 #     if x > y:
       5 #         return x
       6 #     else:
       7 #         return y
       8 #
       9 #
      10 # def max4(a,b,c,d):
      11 #     # 第一步:比较a,b得到res1
      12 #     res1=max2(a,b)
      13 #     # 第二步:比较res1,c得到res2
      14 #     res2=max2(res1,c)
      15 #     # 第三步:比较res2,d得到res3
      16 #     res3=max2(res2,d)
      17 #     return res3
      18 #
      19 # res=max4(1,2,3,4)
      20 # print(res)
      21 
      22 
      23 # 2、函数的嵌套定义:在函数内定义其他函数
      24 # def f1():
      25 #     def f2():
      26 #         pass
      27 
      28 
      29 # 圆形
      30 # 求圆形的求周长:2*pi*radius
      31 def circle(radius,action=0):
      32     from math import pi
      33 
      34     def perimiter(radius):
      35         return 2*pi*radius
      36 
      37     # 求圆形的求面积:pi*(radius**2)
      38     def area(radius):
      39         return pi*(radius**2)
      40 
      41     if action == 0:
      42         return 2*pi*radius
      43 
      44     elif action == 1:
      45         return area(radius)
      46 
      47 circle(33,action=0)
      函数嵌套
        1 # 一:大前提:
        2 # 闭包函数=名称空间与作用域+函数嵌套+函数对象
        3 #        核心点:名字的查找关系是以函数定义阶段为准
        4 
        5 # 二:什么是闭包函数
        6 # "闭"函数指的该函数是内嵌函数
        7 # "包"函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
        8 
        9 # 闭包函数:名称空间与作用域的应用+函数嵌套
       10 # def f1():
       11 #     x = 33333333333333333333
       12 #     def f2():
       13 #         print(x)
       14 #     f2()
       15 #
       16 #
       17 # x=11111
       18 # def bar():
       19 #     x=444444
       20 #     f1()
       21 #
       22 # def foo():
       23 #     x=2222
       24 #     bar()
       25 #
       26 # foo()
       27 
       28 
       29 
       30 # 闭包函数:函数对象
       31 # def f1():
       32 #     x = 33333333333333333333
       33 #     def f2():
       34 #         print('函数f2:',x)
       35 #     return f2
       36 #
       37 # f=f1()
       38 # # print(f)
       39 #
       40 # # x=4444
       41 # # f()
       42 # def foo():
       43 #     x=5555
       44 #     f()
       45 #
       46 # foo()
       47 
       48 
       49 # 三:为何要有闭包函数=》闭包函数的应用
       50 # 两种为函数体传参的方式
       51 # 方式一:直接把函数体需要的参数定义成形参
       52 # def f2(x):
       53 #     print(x)
       54 #
       55 # f2(1)
       56 # f2(2)
       57 # f2(3)
       58 
       59 # 方式二:
       60 # def f1(x): # x=3
       61 #     x=3
       62 #     def f2():
       63 #         print(x)
       64 #     return f2
       65 #
       66 # x=f1(3)
       67 # print(x)
       68 #
       69 # x()
       70 
       71 
       72 
       73 import requests
       74 
       75 # 传参的方案一:
       76 # def get(url):
       77 #     response=requests.get(url)
       78 #     print(len(response.text))
       79 #
       80 # get('https://www.baidu.com')
       81 # get('https://www.cnblogs.com/linhaifeng')
       82 # get('https://zhuanlan.zhihu.com/p/109056932')
       83 
       84 
       85 # 传参的方案二:
       86 def outter(url):
       87     # url='https://www.baidu.com'
       88     def get():
       89         response=requests.get(url)
       90         print(len(response.text))
       91     return get
       92 
       93 baidu=outter('https://www.baidu.com')
       94 baidu()
       95 
       96 cnblogs=outter('https://www.cnblogs.com/linhaifeng')
       97 cnblogs()
       98 
       99 zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')
      100 zhihu()
      闭包函数
    • 3 装饰器
       1 # 一:储备知识
       2 #1、 *args, **kwargs
       3 # def index(x,y):
       4 #     print(x,y)
       5 #
       6 #
       7 # def wrapper(*args,**kwargs):
       8 #     index(*args,**kwargs) #
       9 #                           # index(y=222,x=111)
      10 # wrapper(y=222,x=111)
      11 
      12 
      13 # 2、名称空间与作用域:名称空间的的"嵌套"关系是在函数定义阶段,即检测语法的时候确定的
      14 
      15 # 3、函数对象:
      16 #    可以把函数当做参数传入
      17 #    可以把函数当做返回值返回
      18 # def index():
      19 #     return 123
      20 #
      21 # def foo(func):
      22 #     return func
      23 #
      24 # foo(index)
      25 
      26 # 4、函数的嵌套定义:
      27 # def outter(func):
      28 #     def wrapper():
      29 #         pass
      30 #     return wrapper
      31 
      32 
      33 # 闭包函数
      34 # def outter():
      35 #     x=111
      36 #     def wrapper():
      37 #         x
      38 #     return wrapper
      39 #
      40 # f=outter()
      41 
      42 
      43 
      44 # 传参的方式一:通过参数的形式为函数体传值
      45 
      46 
      47 # def wrapper(x):
      48 #     print(1)
      49 #     print(2)
      50 #     print(3)
      51 #     x
      52 #
      53 # wrapper(1)
      54 # wrapper(2)
      55 # wrapper(3)
      56 # 传参的方式二:通过闭包的方式为函数体传值
      57 # def outter(x):
      58 #     # x=1
      59 #     def wrapper():
      60 #         print(1)
      61 #         print(2)
      62 #         print(3)
      63 #         x
      64 #     return wrapper # return outter内的wrapper那个函数的内地址
      65 #
      66 # # f1=outter(1)
      67 # # f2=outter(2)
      68 # # f3=outter(3)
      69 #
      70 #
      71 # wrapper=outter(1)
      72 #
      知识储备
        1 """
        2 1、什么是装饰器
        3     器指的是工具,可以定义成成函数
        4     装饰指的是为其他事物添加额外的东西点缀
        5     
        6     合到一起的解释:
        7         装饰器指的定义一个函数,该函数是用来为其他函数添加额外的功能
        8         
        9     
       10 2、为何要用装饰器
       11     开放封闭原则
       12         开放:指的是对拓展功能是开放的
       13         封闭:指的是对修改源代码是封闭的
       14         
       15     装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能
       16 3、如何用
       17 """
       18 # 需求:在不修改index函数的源代码以及调用方式的前提下为其添加统计运行时间的功能
       19 # def index(x,y):
       20 #     time.sleep(3)
       21 #     print('index %s %s' %(x,y))
       22 #
       23 # index(111,222)
       24 # # index(y=111,x=222)
       25 # # index(111,y=222)
       26 
       27 # 解决方案一:失败
       28 # 问题:没有修改被装饰对象的调用方式,但是修改了其源代码
       29 # import time
       30 #
       31 # def index(x,y):
       32 #     start=time.time()
       33 #     time.sleep(3)
       34 #     print('index %s %s' %(x,y))
       35 #     stop = time.time()
       36 #     print(stop - start)
       37 #
       38 # index(111,222)
       39 
       40 
       41 # 解决方案二:失败
       42 # 问题:没有修改被装饰对象的调用方式,也没有修改了其源代码,并且加上了新功能
       43 #      但是代码冗余
       44 # import time
       45 #
       46 # def index(x,y):
       47 #     time.sleep(3)
       48 #     print('index %s %s' %(x,y))
       49 #
       50 # start=time.time()
       51 # index(111,222)
       52 # stop=time.time()
       53 # print(stop - start)
       54 #
       55 #
       56 #
       57 # start=time.time()
       58 # index(111,222)
       59 # stop=time.time()
       60 # print(stop - start)
       61 #
       62 #
       63 # start=time.time()
       64 # index(111,222)
       65 # stop=time.time()
       66 # print(stop - start)
       67 
       68 
       69 # 解决方案三:失败
       70 # 问题:解决了方案二代码冗余问题,但带来一个新问题即函数的调用方式改变了
       71 # import time
       72 #
       73 # def index(x,y):
       74 #     time.sleep(3)
       75 #     print('index %s %s' %(x,y))
       76 #
       77 # def wrapper():
       78 #     start=time.time()
       79 #     index(111,222)
       80 #     stop=time.time()
       81 #     print(stop - start)
       82 #
       83 # wrapper()
       84 
       85 # 方案三的优化一:将index的参数写活了
       86 # import time
       87 #
       88 # def index(x,y,z):
       89 #     time.sleep(3)
       90 #     print('index %s %s %s' %(x,y,z))
       91 #
       92 # def wrapper(*args,**kwargs):
       93 #     start=time.time()
       94 #     index(*args,**kwargs) # index(3333,z=5555,y=44444)
       95 #     stop=time.time()
       96 #     print(stop - start)
       97 #
       98 # # wrapper(3333,4444,5555)
       99 # # wrapper(3333,z=5555,y=44444)
      100 
      101 
      102 # 方案三的优化二:在优化一的基础上把被装饰对象写活了,原来只能装饰index
      103 # import time
      104 #
      105 # def index(x,y,z):
      106 #     time.sleep(3)
      107 #     print('index %s %s %s' %(x,y,z))
      108 #
      109 # def home(name):
      110 #     time.sleep(2)
      111 #     print('welcome %s to home page' %name)
      112 #
      113 #
      114 # def outter(func):
      115 #     # func = index的内存地址
      116 #     def wrapper(*args,**kwargs):
      117 #         start=time.time()
      118 #         func(*args,**kwargs) # index的内存地址()
      119 #         stop=time.time()
      120 #         print(stop - start)
      121 #     return wrapper
      122 #
      123 # index=outter(index) # index=wrapper的内存地址
      124 # home=outter(home) # home=wrapper的内存地址
      125 #
      126 #
      127 # home('egon')
      128 # # home(name='egon')
      129 
      130 # 方案三的优化三:将wrapper做的跟被装饰对象一模一样,以假乱真
      131 # import time
      132 #
      133 # def index(x,y,z):
      134 #     time.sleep(3)
      135 #     print('index %s %s %s' %(x,y,z))
      136 #
      137 # def home(name):
      138 #     time.sleep(2)
      139 #     print('welcome %s to home page' %name)
      140 #
      141 # def outter(func):
      142 #     def wrapper(*args,**kwargs):
      143 #         start=time.time()
      144 #         res=func(*args,**kwargs)
      145 #         stop=time.time()
      146 #         print(stop - start)
      147 #         return res
      148 #
      149 #
      150 #
      151 #     return wrapper
      152 # # 偷梁换柱:home这个名字指向的wrapper函数的内存地址
      153 # home=outter(home)
      154 #
      155 #
      156 # res=home('egon') # res=wrapper('egon')
      157 # print('返回值--》',res)
      158 
      159 # 大方向:如何在方案三的基础上不改变函数的调用方式
      160 
      161 
      162 
      163 
      164 # 语法糖:让你开心的语法
      165 import time
      166 
      167 # 装饰器
      168 # def timmer(func):
      169 #     def wrapper(*args,**kwargs):
      170 #         start=time.time()
      171 #         res=func(*args,**kwargs)
      172 #         stop=time.time()
      173 #         print(stop - start)
      174 #         return res
      175 #
      176 #
      177 #
      178 #     return wrapper
      179 #
      180 #
      181 # # 在被装饰对象正上方的单独一行写@装饰器名字
      182 # # @timmer # index=timmer(index)
      183 # def index(x,y,z):
      184 #     time.sleep(3)
      185 #     print('index %s %s %s' %(x,y,z))
      186 #
      187 # # @timmer # home=timmer(ome)
      188 # def home(name):
      189 #     time.sleep(2)
      190 #     print('welcome %s to home page' %name)
      191 #
      192 #
      193 # index(x=1,y=2,z=3)
      194 # home('egon')
      195 
      196 
      197 
      198 # 思考题(选做),叠加多个装饰器,加载顺序与运行顺序
      199 # @deco1 # index=deco1(deco2.wrapper的内存地址)
      200 # @deco2 # deco2.wrapper的内存地址=deco2(deco3.wrapper的内存地址)
      201 # @deco3 # deco3.wrapper的内存地址=deco3(index)
      202 # def index():
      203 #     pass
      204 
      205 
      206 
      207 # 总结无参装饰器模板
      208 # def outter(func):
      209 #     def wrapper(*args,**kwargs):
      210 #         # 1、调用原函数
      211 #         # 2、为其增加新功能
      212 #         res=func(*args,**kwargs)
      213 #         return res
      214 #     return wrapper
      215 
      216 
      217 
      218 
      219 
      220 
      221 
      222 
      223 def auth(func):
      224     def wrapper(*args,**kwargs):
      225         # 1、调用原函数
      226         # 2、为其增加新功能
      227         name=input('your name>>: ').strip()
      228         pwd=input('your password>>: ').strip()
      229         if name == 'egon' and pwd == '123':
      230             res=func(*args,**kwargs)
      231             return res
      232         else:
      233             print('账号密码错误')
      234     return wrapper
      235 
      236 
      237 
      238 @auth
      239 def index():
      240     print('from index')
      241 
      242 index()
      无参装饰器
       1 # 一、叠加多个装饰器的加载、运行分析(了解***)
       2 
       3 def deco1(func1): # func1 = wrapper2的内存地址
       4     def wrapper1(*args,**kwargs):
       5         print('正在运行===>deco1.wrapper1')
       6         res1=func1(*args,**kwargs)
       7         return res1
       8     return wrapper1
       9 
      10 def deco2(func2): # func2 = wrapper3的内存地址
      11     def wrapper2(*args,**kwargs):
      12         print('正在运行===>deco2.wrapper2')
      13         res2=func2(*args,**kwargs)
      14         return res2
      15     return wrapper2
      16 
      17 def deco3(x):
      18     def outter3(func3): # func3=被装饰对象index函数的内存地址
      19         def wrapper3(*args,**kwargs):
      20             print('正在运行===>deco3.outter3.wrapper3')
      21             res3=func3(*args,**kwargs)
      22             return res3
      23         return wrapper3
      24     return outter3
      25 
      26 
      27 # 加载顺序自下而上(了解)
      28 @deco1      # index=deco1(wrapper2的内存地址)        ===> index=wrapper1的内存地址
      29 @deco2      # index=deco2(wrapper3的内存地址)        ===> index=wrapper2的内存地址
      30 @deco3(111) # ===>@outter3===> index=outter3(index) ===> index=wrapper3的内存地址
      31 def index(x,y):
      32     print('from index %s:%s' %(x,y))
      33 
      34 # 执行顺序自上而下的,即wraper1-》wrapper2-》wrapper3
      35 index(1,2) # wrapper1(1,2)
      叠加多个装饰器分析
       1 #偷梁换柱,即将原函数名指向的内存地址偷梁换柱成wrapper函数
       2 #        所以应该将wrapper做的跟原函数一样才行
       3 from functools import wraps
       4 
       5 def outter(func):
       6     @wraps(func)
       7     def wrapper(*args, **kwargs):
       8         """这个是主页功能"""
       9         res = func(*args, **kwargs) # res=index(1,2)
      10         return res
      11 
      12     # 手动将原函数的属性赋值给wrapper函数
      13     # 1、函数wrapper.__name__ = 原函数.__name__
      14     # 2、函数wrapper.__doc__ = 原函数.__doc__
      15     # wrapper.__name__ = func.__name__
      16     # wrapper.__doc__ = func.__doc__
      17 
      18     return wrapper
      19 
      20 
      21 
      22 @outter # index=outter(index)
      23 def index(x,y):
      24     """这个是主页功能"""
      25     print(x,y)
      26 
      27 
      28 print(index.__name__)
      29 print(index.__doc__) #help(index)
      functool函数的使用
        1 # 一:知识储备
        2 # 由于语法糖@的限制,outter函数只能有一个参数,并且该才是只用来接收
        3 #                                       被装饰对象的内存地址
        4 # def outter(func):
        5 #     # func = 函数的内存地址
        6 #     def wrapper(*args,**kwargs):
        7 #         res=func(*args,**kwargs)
        8 #         return res
        9 #     return wrapper
       10 #
       11 # # @outter # index=outter(index) # index=>wrapper
       12 # @outter # outter(index)
       13 # def index(x,y):
       14 #     print(x,y)
       15 
       16 # 偷梁换柱之后
       17 # index的参数什么样子,wrapper的参数就应该什么样子
       18 # index的返回值什么样子,wrapper的返回值就应该什么样子
       19 # index的属性什么样子,wrapper的属性就应该什么样子==》from functools import wraps
       20 
       21 
       22 # 山炮玩法:
       23 # def auth(func,db_type):
       24 #     def wrapper(*args, **kwargs):
       25 #         name=input('your name>>>: ').strip()
       26 #         pwd=input('your password>>>: ').strip()
       27 #
       28 #         if db_type == 'file':
       29 #             print('基于文件的验证')
       30 #             if name == 'egon' and pwd == '123':
       31 #                 res = func(*args, **kwargs)
       32 #                 return res
       33 #             else:
       34 #                 print('user or password error')
       35 #         elif db_type == 'mysql':
       36 #             print('基于mysql的验证')
       37 #         elif db_type == 'ldap':
       38 #             print('基于ldap的验证')
       39 #         else:
       40 #             print('不支持该db_type')
       41 #
       42 #     return wrapper
       43 #
       44 # # @auth  # 账号密码的来源是文件
       45 # def index(x,y):
       46 #     print('index->>%s:%s' %(x,y))
       47 #
       48 # # @auth # 账号密码的来源是数据库
       49 # def home(name):
       50 #     print('home->>%s' %name)
       51 #
       52 # # @auth # 账号密码的来源是ldap
       53 # def transfer():
       54 #     print('transfer')
       55 #
       56 #
       57 # index=auth(index,'file')
       58 # home=auth(home,'mysql')
       59 # transfer=auth(transfer,'ldap')
       60 #
       61 # # index(1,2)
       62 # # home('egon')
       63 # # transfer()
       64 
       65 
       66 # 山炮二
       67 # def auth(db_type):
       68 #     def deco(func):
       69 #         def wrapper(*args, **kwargs):
       70 #             name=input('your name>>>: ').strip()
       71 #             pwd=input('your password>>>: ').strip()
       72 #
       73 #             if db_type == 'file':
       74 #                 print('基于文件的验证')
       75 #                 if name == 'egon' and pwd == '123':
       76 #                     res = func(*args, **kwargs)
       77 #                     return res
       78 #                 else:
       79 #                     print('user or password error')
       80 #             elif db_type == 'mysql':
       81 #                 print('基于mysql的验证')
       82 #             elif db_type == 'ldap':
       83 #                 print('基于ldap的验证')
       84 #             else:
       85 #                 print('不支持该db_type')
       86 #
       87 #         return wrapper
       88 #     return deco
       89 #
       90 # deco=auth(db_type='file')
       91 # @deco # 账号密码的来源是文件
       92 # def index(x,y):
       93 #     print('index->>%s:%s' %(x,y))
       94 #
       95 # deco=auth(db_type='mysql')
       96 # @deco # 账号密码的来源是数据库
       97 # def home(name):
       98 #     print('home->>%s' %name)
       99 #
      100 # deco=auth(db_type='ldap')
      101 # @deco # 账号密码的来源是ldap
      102 # def transfer():
      103 #     print('transfer')
      104 #
      105 #
      106 # index(1,2)
      107 # home('egon')
      108 # transfer()
      109 
      110 
      111 # 语法糖
      112 def auth(db_type):
      113     def deco(func):
      114         def wrapper(*args, **kwargs):
      115             name = input('your name>>>: ').strip()
      116             pwd = input('your password>>>: ').strip()
      117 
      118             if db_type == 'file':
      119                 print('基于文件的验证')
      120                 if name == 'egon' and pwd == '123':
      121                     res = func(*args, **kwargs)  # index(1,2)
      122                     return res
      123                 else:
      124                     print('user or password error')
      125             elif db_type == 'mysql':
      126                 print('基于mysql的验证')
      127             elif db_type == 'ldap':
      128                 print('基于ldap的验证')
      129             else:
      130                 print('不支持该db_type')
      131         return wrapper
      132     return deco
      133 
      134 
      135 @auth(db_type='file')  # @deco # index=deco(index) # index=wrapper
      136 def index(x, y):
      137     print('index->>%s:%s' % (x, y))
      138 
      139 @auth(db_type='mysql')  # @deco # home=deco(home) # home=wrapper
      140 def home(name):
      141     print('home->>%s' % name)
      142 
      143 
      144 @auth(db_type='ldap')  # 账号密码的来源是ldap
      145 def transfer():
      146     print('transfer')
      147 
      148 # index(1, 2)
      149 # home('egon')
      150 # transfer()
      151 
      152 
      153 
      154 
      155 # 有参装饰器模板
      156 def 有参装饰器(x,y,z):
      157     def outter(func):
      158         def wrapper(*args, **kwargs):
      159             res = func(*args, **kwargs)
      160             return res
      161         return wrapper
      162     return outter
      163 
      164 @有参装饰器(1,y=2,z=3)
      165 def 被装饰对象():
      166     pass
      有参装饰器
    • 4 迭代器&生成器
        1 '''
        2 1、什么是迭代器
        3     迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复
        4     都是基于上一次的结果而继续的,单纯的重复并不是迭代
        5     
        6 2、为何要有迭代器
        7     迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型
        8     有:列表、字符串、元组、字典、集合、打开文件
        9     
       10     l=['egon','liu','alex']
       11     i=0
       12     while i < len(l):
       13         print(l[i])
       14         i+=1
       15         
       16     上述迭代取值的方式只适用于有索引的数据类型:列表、字符串、元组
       17     为了解决基于索引迭代器取值的局限性
       18     python必须提供一种能够不依赖于索引的取值方式,这就是迭代器
       19 
       20 
       21 3、如何用迭代器
       22     
       23 '''
       24 # 1、可迭代的对象:但凡内置有__iter__方法的都称之为可迭代的对象
       25 # s1=''
       26 # # s1.__iter__()
       27 #
       28 # l=[]
       29 # # l.__iter__()
       30 #
       31 # t=(1,)
       32 # # t.__iter__()
       33 #
       34 # d={'a':1}
       35 # # d.__iter__()
       36 #
       37 # set1={1,2,3}
       38 # # set1.__iter__()
       39 #
       40 # with open('a.txt',mode='w') as f:
       41 #     # f.__iter__()
       42 #     pass
       43 
       44 # 2、调用可迭代对象下的__iter__方法会将其转换成迭代器对象
       45 d={'a':1,'b':2,'c':3}
       46 d_iterator=d.__iter__()
       47 # print(d_iterator)
       48 
       49 # print(d_iterator.__next__())
       50 # print(d_iterator.__next__())
       51 # print(d_iterator.__next__())
       52 # print(d_iterator.__next__()) # 抛出异常StopIteration
       53 
       54 
       55 # while True:
       56 #     try:
       57 #         print(d_iterator.__next__())
       58 #     except StopIteration:
       59 #         break
       60 #
       61 # print('====>>>>>>') # 在一个迭代器取值取干净的情况下,再对其取值娶不到
       62 # d_iterator=d.__iter__()
       63 # while True:
       64 #     try:
       65 #         print(d_iterator.__next__())
       66 #     except StopIteration:
       67 #         break
       68 
       69 
       70 # l=[1,2,3,4,5]
       71 # l_iterator=l.__iter__()
       72 #
       73 # while True:
       74 #     try:
       75 #         print(l_iterator.__next__())
       76 #     except StopIteration:
       77 #         break
       78 
       79 
       80 # 3、可迭代对象与迭代器对象详解
       81 # 3.1 可迭代对象("可以转换成迭代器的对象"):内置有__iter__方法对象
       82 #        可迭代对象.__iter__(): 得到迭代器对象
       83 
       84 # 3.2 迭代器对象:内置有__next__方法并且内置有__iter__方法的对象
       85 #        迭代器对象.__next__():得到迭代器的下一个值
       86 #        迭代器对象.__iter__():得到迭代器的本身,说白了调了跟没调一个样子
       87 # dic={'a':1,'b':2,'c':3}
       88 #
       89 # dic_iterator=dic.__iter__()
       90 # print(dic_iterator is dic_iterator.__iter__().__iter__().__iter__())
       91 #
       92 
       93 # 4、可迭代对象:字符串、列表、元组、字典、集合、文件对象
       94 # 迭代器对象:文件对象
       95 # s1=''
       96 # s1.__iter__()
       97 #
       98 # l=[]
       99 # l.__iter__()
      100 #
      101 # t=(1,)
      102 # t.__iter__()
      103 #
      104 #
      105 # d={'a':1}
      106 # d.__iter__()
      107 #
      108 # set1={1,2,3}
      109 # set1.__iter__()
      110 #
      111 #
      112 # with open('a.txt',mode='w') as f:
      113 #     f.__iter__()
      114 #     f.__next__()
      115 
      116 
      117 
      118 
      119 
      120 # 5、for循环的工作原理:for循环可以称之为叫迭代器循环
      121 d={'a':1,'b':2,'c':3}
      122 
      123 # 1、d.__iter__()得到一个迭代器对象
      124 # 2、迭代器对象.__next__()拿到一个返回值,然后将该返回值赋值给k
      125 # 3、循环往复步骤2,直到抛出StopIteration异常for循环会捕捉异常然后结束循环
      126 # for k in d:
      127 #     print(k)
      128 
      129 
      130 # with open('a.txt',mode='rt',encoding='utf-8') as f:
      131 #     for line in f: # f.__iter__()
      132 #         print(line)
      133 
      134 
      135 # list('hello') #原理同for循环
      136 
      137 # 6、迭代器优缺点总结
      138 # 6.1 缺点:
      139 # I、为序列和非序列类型提供了一种统一的迭代取值方式。
      140 # II、惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。
      141 
      142 # 6.2 缺点:
      143 # I、除非取尽,否则无法获取迭代器的长度
      144 #
      145 # II、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。
      迭代器
       1 # 如何得到自定义的迭代器:
       2 # 在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
       3 # 会返回一个生成器对象,生成器即自定义的迭代器
       4 def func():
       5     print('第一次')
       6     yield 1
       7     print('第二次')
       8     yield 2
       9     print('第三次')
      10     yield 3
      11     print('第四次')
      12 
      13 
      14 # g=func()
      15 # print(g)
      16 # 生成器就是迭代器
      17 # g.__iter__()
      18 # g.__next__()
      19 
      20 
      21 # 会触发函数体代码的运行,然后遇到yield停下来,将yield后的值
      22 # 当做本次调用的结果返回
      23 # res1=g.__next__()
      24 # print(res1)
      25 #
      26 #
      27 # res2=g.__next__()
      28 # print(res2)
      29 #
      30 # res3=g.__next__()
      31 # print(res3)
      32 #
      33 # res4=g.__next__()
      34 
      35 
      36 
      37 # len('aaa') # 'aaa'.__len__()
      38 
      39 # next(g)    # g.__next__()
      40 # iter(可迭代对象)     # 可迭代对象.__iter__()
      41 
      42 
      43 # 应用案列
      44 def my_range(start,stop,step=1):
      45     # print('start...')
      46     while start < stop:
      47         yield start
      48         start+=step
      49     # print('end....')
      50 
      51 
      52 # g=my_range(1,5,2) # 1 3
      53 # print(next(g))
      54 # print(next(g))
      55 # print(next(g))
      56 
      57 for n in my_range(1,7,2):
      58     print(n)
      59 
      60 
      61 # 总结yield:
      62 # 有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
      生成器
       1 # x=yield 返回值
       2 
       3 # 一:
       4 # def dog(name):
       5 #     print('道哥%s准备吃东西啦...' %name)
       6 #     while True:
       7 #         # x拿到的是yield接收到的值
       8 #         x = yield # x = '肉包子'
       9 #         print('道哥%s吃了 %s' %(name,x))
      10 #
      11 #
      12 # g=dog('alex')
      13 # g.send(None) # 等同于next(g)
      14 #
      15 # g.send(['一根骨头','aaa'])
      16 # # g.send('肉包子')
      17 # # g.send('一同泔水')
      18 # # g.close()
      19 # # g.send('1111') # 关闭之后无法传值
      20 
      21 
      22 # 二:
      23 def dog(name):
      24     food_list=[]
      25     print('道哥%s准备吃东西啦...' %name)
      26     while True:
      27         # x拿到的是yield接收到的值
      28         x = yield food_list # x = '肉包子'
      29         print('道哥%s吃了 %s' %(name,x))
      30         food_list.append(x) # ['一根骨头','肉包子']
      31 #
      32 # g=dog('alex')
      33 # res=g.send(None)  # next(g)
      34 # print(res)
      35 #
      36 # res=g.send('一根骨头')
      37 # print(res)
      38 #
      39 # res=g.send('肉包子')
      40 # print(res)
      41 # # g.send('一同泔水')
      42 
      43 
      44 
      45 
      46 def func():
      47     print('start.....')
      48     x=yield 1111  # x='xxxxx'
      49     print('哈哈哈啊哈')
      50     print('哈哈哈啊哈')
      51     print('哈哈哈啊哈')
      52     print('哈哈哈啊哈')
      53     yield 22222
      54 
      55 g=func()
      56 res=next(g)
      57 print(res)
      58 
      59 res=g.send('xxxxx')
      60 print(res)
      yield表达式
    • 5 三元表达式&列表生成式&递归
       1 # 针对以下需求
       2 # def func(x,y):
       3 #     if x > y:
       4 #         return x
       5 #     else:
       6 #         return y
       7 #
       8 # res=func(1,2)
       9 # print(res)
      10 
      11 # 三元表达式
      12 # 语法格式: 条件成立时要返回的值 if 条件 else 条件不成立时要返回的值
      13 x=1
      14 y=2
      15 
      16 # res=x if x > y else y
      17 # print(res)
      18 
      19 
      20 res=111111 if 'egon' == 'egon' else 2222222222
      21 print(res)
      22 
      23 
      24 
      25 # 应用举例
      26 def func():
      27     # if 1 > 3:
      28     #     x=1
      29     # else:
      30     #     x=3
      31 
      32     x = 1 if 1 > 3 else 3
      三元表达式
       1 # 1、列表生成式
       2 l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon']
       3 # new_l=[]
       4 # for name in l:
       5 #     if name.endswith('dsb'):
       6 #         new_l.append(name)
       7 
       8 
       9 # new_l=[name for name in l if name.endswith('dsb')]
      10 # new_l=[name for name in l]
      11 
      12 # print(new_l)
      13 
      14 # 把所有小写字母全变成大写
      15 # new_l=[name.upper() for name in l]
      16 # print(new_l)
      17 
      18 # 把所有的名字去掉后缀_dsb
      19 # new_l=[name.replace('_dsb','') for name in l]
      20 # print(new_l)
      21 
      22 # 2、字典生成式
      23 # keys=['name','age','gender']
      24 # dic={key:None for key in keys}
      25 # print(dic)
      26 
      27 # items=[('name','egon'),('age',18),('gender','male')]
      28 # res={k:v for k,v in items if k != 'gender'}
      29 # print(res)
      30 
      31 # 3、集合生成式
      32 # keys=['name','age','gender']
      33 # set1={key for key in keys}
      34 # print(set1,type(set1))
      35 
      36 
      37 # 4、生成器表达式
      38 # g=(i for i in range(10) if i > 3)
      39 # !!!!!!!!!!!强调!!!!!!!!!!!!!!!
      40 # 此刻g内部一个值也没有
      41 
      42 # print(g,type(g))
      43 
      44 # print(g)
      45 # print(next(g))
      46 # print(next(g))
      47 # print(next(g))
      48 # print(next(g))
      49 # print(next(g))
      50 # print(next(g))
      51 # print(next(g))
      52 
      53 
      54 with open('笔记.txt', mode='rt', encoding='utf-8') as f:
      55     # 方式一:
      56     # res=0
      57     # for line in f:
      58     #     res+=len(line)
      59     # print(res)
      60 
      61     # 方式二:
      62     # res=sum([len(line) for line in f])
      63     # print(res)
      64 
      65     # 方式三 :效率最高
      66     # res = sum((len(line) for line in f))
      67     # 上述可以简写为如下形式
      68     res = sum(len(line) for line in f)
      69     print(res)
      列表生成式
       1 # 一:递归的定义
       2 # 函数的递归调用:是函数嵌套调用的一种特殊形式
       3 # 具体是指:
       4 #        在调用一个函数的过程中又直接或者间接地调用到本身
       5 
       6 # 直接调用本身
       7 # def f1():
       8 #     print('是我是我还是我')
       9 #     f1()
      10 # f1()
      11 
      12 # 间接接调用本身
      13 # def f1():
      14 #     print('===>f1')
      15 #     f2()
      16 #
      17 # def f2():
      18 #     print('===>f2')
      19 #     f1()
      20 #
      21 # f1()
      22 
      23 
      24 # 一段代码的循环运行的方案有两种
      25 # 方式一:while、for循环
      26 # while True:
      27 #     print(1111)
      28 #     print(2222)
      29 #     print(3333)
      30 
      31 # 方式二:递归的本质就是循环:
      32 # def f1():
      33 #     print(1111)
      34 #     print(2222)
      35 #     print(3333)
      36 #     f1()
      37 # f1()
      38 
      39 
      40 # 二:需要强调的的一点是:
      41 # 递归调用不应该无限地调用下去,必须在满足某种条件下结束递归调用
      42 # n=0
      43 # while n < 10:
      44 #     print(n)
      45 #     n+=1
      46 
      47 
      48 # def f1(n):
      49 #     if n == 10:
      50 #         return
      51 #     print(n)
      52 #     n+=1
      53 #     f1(n)
      54 #
      55 # f1(0)
      56 
      57 # 三:递归的两个阶段
      58 # 回溯:一层一层调用下去
      59 # 递推:满足某种结束条件,结束递归调用,然后一层一层返回
      60 
      61 # age(5) = age(4) + 10
      62 # age(4) = age(3) + 10
      63 # age(3) = age(2) + 10
      64 # age(2) = age(1) + 10
      65 # age(1) = 18
      66 
      67 # def age(n):
      68 #     if n == 1:
      69 #         return 18
      70 #     return age(n-1) + 10
      71 #
      72 #
      73 # res=age(5)
      74 # print(res)
      75 
      76 # 四:递归的应用
      77 l=[1,2,[3,[4,[5,[6,[7,[8,[9,10,11,[12,[13,]]]]]]]]]]
      78 
      79 def f1(list1):
      80     for x in list1:
      81         if type(x) is list:
      82             # 如果是列表,应该再循环、再判断,即重新运行本身的代码
      83             f1(x)
      84         else:
      85             print(x)
      86 
      87 f1(l)
      递归
    • 6 二分法&匿名函数
       1 # 算法:是高效解决问题的办法
       2 # 算法之二分法
       3 
       4 # 需求:有一个按照从小到大顺序排列的数字列表
       5 #      需要从该数字列表中找到我们想要的那个一个数字
       6 #      如何做更高效???
       7 
       8 
       9 nums=[-3,4,7,10,13,21,43,77,89]
      10 find_num=10
      11 
      12 nums=[-3,4,13,10,-2,7,89]
      13 nums.sort()
      14 print(nums)
      15 
      16 # 方案一:整体遍历效率太低
      17 # for num in nums:
      18 #     if num == find_num:
      19 #         print('find it')
      20 #         break
      21 
      22 # 方案二:二分法
      23 # def binary_search(find_num,列表):
      24 #     mid_val=找列表中间的值
      25 #     if find_num > mid_val:
      26 #         # 接下来的查找应该是在列表的右半部分
      27 #         列表=列表切片右半部分
      28 #         binary_search(find_num,列表)
      29 #     elif find_num < mid_val:
      30 #         # 接下来的查找应该是在列表的左半部分
      31 #         列表=列表切片左半部分
      32 #         binary_search(find_num,列表)
      33 #     else:
      34 #         print('find it')
      35 
      36 # nums=[-3,4,7,10,13,21,43,77,89]
      37 # find_num=8
      38 # def binary_search(find_num,l):
      39 #     print(l)
      40 #     if len(l) == 0:
      41 #         print('找的值不存在')
      42 #         return
      43 #     mid_index=len(l) // 2
      44 #
      45 #     if find_num > l[mid_index]:
      46 #         # 接下来的查找应该是在列表的右半部分
      47 #         l=l[mid_index+1:]
      48 #         binary_search(find_num,l)
      49 #     elif find_num < l[mid_index]:
      50 #         # 接下来的查找应该是在列表的左半部分
      51 #         l=l[:mid_index]
      52 #         binary_search(find_num,l)
      53 #     else:
      54 #         print('find it')
      55 #
      56 # binary_search(find_num,nums)
      二分法
       1 # 1、def用于定义有名函数
       2 # func=函数的内存地址
       3 # def func(x,y):
       4 #     return x+y
       5 
       6 # print(func)
       7 # 2、lamdab用于定义匿名函数
       8 # print(lambda x,y:x+y)
       9 
      10 
      11 # 3、调用匿名函数
      12 # 方式一:
      13 # res=(lambda x,y:x+y)(1,2)
      14 # print(res)
      15 
      16 # 方式二:
      17 # func=lambda x,y:x+y
      18 # res=func(1,2)
      19 # print(res)
      20 
      21 #4、匿名用于临时调用一次的场景:更多的是将匿名与其他函数配合使用
      匿名函数介绍
       1 salaries={
       2     'siry':3000,
       3     'tom':7000,
       4     'lili':10000,
       5     'jack':2000
       6 }
       7 # 需求1:找出薪资最高的那个人=》lili
       8 # res=max([3,200,11,300,399])
       9 # print(res)
      10 
      11 # res=max(salaries)
      12 # print(res)
      13 
      14 
      15 salaries={
      16     'siry':3000,
      17     'tom':7000,
      18     'lili':10000,
      19     'jack':2000
      20 }
      21 # 迭代出的内容    比较的值
      22 # 'siry'         3000
      23 # 'tom'          7000
      24 # 'lili'         10000
      25 # 'jack'         2000
      26 
      27 # def func(k):
      28 #     return salaries[k]
      29 
      30 # ========================max的应用
      31 # res=max(salaries,key=func) # 返回值=func('siry')
      32 # print(res)
      33 
      34 # res=max(salaries,key=lambda k:salaries[k])
      35 # print(res)
      36 
      37 # ========================min的应用
      38 # res=min(salaries,key=lambda k:salaries[k])
      39 # print(res)
      40 
      41 
      42 # ========================sorted排序
      43 # salaries={
      44 #     'siry':3000,
      45 #     'tom':7000,
      46 #     'lili':10000,
      47 #     'jack':2000
      48 # }
      49 res=sorted(salaries,key=lambda k:salaries[k],reverse=True)
      50 # print(res)
      51 
      52 # ========================map的应用(了解)
      53 # l=['alex','lxx','wxx','薛贤妻']
      54 # new_l=(name+'_dsb' for name in l)
      55 # print(new_l)
      56 
      57 # res=map(lambda name:name+'_dsb',l)
      58 # print(res) # 生成器
      59 # ========================filter的应用(了解)
      60 # l=['alex_sb','lxx_sb','wxx','薛贤妻']
      61 # res=(name for name in l if name.endswith('sb'))
      62 # print(res)
      63 
      64 # res=filter(lambda name:name.endswith('sb'),l)
      65 # print(res)
      66 
      67 # ========================reduce的应用(了解)
      68 from functools import reduce
      69 res=reduce(lambda x,y:x+y,[1,2,3],10) # 16
      70 print(res)
      71 
      72 res=reduce(lambda x,y:x+y,['a','b','c']) # 'a','b'
      73 print(res)
      匿名函数使用
    作者:华王 博客:https://www.cnblogs.com/huahuawang/
  • 相关阅读:
    伺服电机常见故障分析汇总
    PLC常见四大故障及其处理方法
    Qt QString的arg()方法的使用
    Qt 线程池QThreadPool类、QRunnable类
    C++线程池的实现
    C++ List的用法
    C++语言堆栈的详细讲解
    QT中的QQueue类、C++中的queue类
    Qt platform plugin 'windows' 问题的解决方法
    电气接地的相关介绍
  • 原文地址:https://www.cnblogs.com/huahuawang/p/14724542.html
Copyright © 2020-2023  润新知