第二篇(上)函数

  • 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/
原文地址:https://www.cnblogs.com/huahuawang/p/14724542.html