day04 函数进阶

1.内容回顾


1. 文件操作

  • 打开文件

    • open(‘文件路径’,mode=‘r’,encoding=‘utf-8’)

    • open(‘文件路径’,mode=‘w’,encoding=‘utf-8’)

    • open(‘文件路径’,mode=‘a’,encoding=‘utf-8’)

    • 注:一般不用r+或w+,pycharm创建的文件是utf-8,Windows创建的是gbk模式,以什么方式创建以什么方式打开

    • open(‘文件路径’,mode=‘rb’)

    • open(‘文件路径’,mode=‘wb’)

    • open(‘文件路径’,mode=‘ab’)

      f = open('test',mode='rb')
      content = f.read() #只读
      print(content)
      msg = content.decode('utf-8') #转码
      print(msg)
      f.close()
      
      f = open('test',encoding='utf-8') #读+转码
      content = f.read()
      print(content)
      
  • [外链图片转存失败(img-uhjVlgcT-1564886425126)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564279377373.png)]

  • 读写文件

      • read() #默认读所有
      • read(n) #读n个字节/字符,处理视频时
      • readline() #每次读一行,会记录文件指针,不知道什么时候结束
      • for line in f:
      • write(‘想写啥写啥’)
      • write(b’abc’) #wb写字节,如果以rb方式打开必须这么用
  • 关闭文件

    • f.close()
  • 删除和修改 #关闭文件之后再删除

    • import os
    • os.remove(‘文件的绝对路径’)
    • os.rename(‘原名’,‘目的名’)
    • 修改文件
      • 读a文件,写b文件
      • 删除a,重命名b–>a

2. 工作目录

  • 在哪个路径下执行Python程序,工作目录就是哪里

  • 所以 如果希望在任何一个位置执行代码都不出现文件目录找不到的情况,就要用绝对路径,而不是相对路径

    path = r'G:\py27\day04\test'
    f = open(path,encoding = 'utf-8')
    content = f.read()
    print(content)
    
  • pycharm下会有很多优化机制

    • 在执行代码的时候,会自动的把当前所在的文件目录作为工作目录

3. 初始函数

  • 函数的定义

    • def 函数名(形参):
      • 缩进 函数体
      • return 返回值
  • 调用

    • 变量 = 函数名(实参)
    • 变量就是函数的返回值
  • 返回值

    1. 不写return 默认返回None #None表示空
    2. 只写return 表示函数结束,默认返回None
    3. return 值 值被返回给调用者
    4. return 值1,值2 接收的返回值是元组(值1,值2)
  • 参数

    • 站在调用者的角度上

      • 按照位置传参数

      def cal(a,b,c):
      pass
      cal(1,2,3)

      
      
      
      * *可以迭代的对象(可以被for循环)
      
        ```
        def cal(a,b,c):
        	pass
        l = [1,2,3]
        cal(*l) #-->cal(1[0],1[1],1[2])
        ```
      
      
      
      
    • 按照关键字传参

      def cal(a,b,c):
      	pass
      cal(a = 1,b = 2,c = 3)
      
      • **字典

        def cal(a,b,c):
        	pass
        d = {'a':1,'b':2,'c':3}
        cal(**d) #按照关键字传参,字典特有
        
      • 混合:先位置,在关键字

        def cal(a,b,c):
        	pass
        cal(1,2,c = 3)
        
    • 站在定义函数的角度上(定义参数要按以下顺序)

      • 位置参数

      • *args 动态参数 #默认参数不能再动态参数之前

      • 默认参数

      • **kwargs 动态参数

        def cal(a,b,*args,c = 10,d = '男',**kwargs)
        #按照这个顺序调用,中间的默认参数可以设置多个
        
    • 参数的陷阱,如果默认参数的值是一个可变数据类型

    • 那么所有的调用者都共享这一个数据

    • 这个变量是在定义的时候创建1次,而不会在调用的过程中再次被创建了

      def func(l = []): #这个列表在定义的时候已经被创建出来,再次调用不会再创建了
      	l.append(1)
      	print(l)
      	
      func()
      func()
      结果:
      

    [1]
    [1,1]

    
    

    def func(a,l = []):
    print(id(l))
    l.append(a)
    print(l)
    return l

    func(1) #没传传参数就用默认列表
    func(2,[]) #因为传了[]就往[]里传参数
    func(3) #没传参数,就用默认列表就放3
    func(4,[]) # [4]

    
    

    def func(a,l = []):
    print(id(l))
    l.append(a)
    print(l)
    return l

    func(1)
    l1 = func(2,[])
    func(3)
    func(4,[]) # [4]

    
    
    
    

2.今日内容


1. 装饰器

  • import time #时间模块

    • 被人写好的一些功能,放在一个模块里
    • 和时间相关的功能,就放在了time模块
    import time
    print(time.time())
    1564282438.9430697
    # 格林威治时间 - 19700101 08:0:00 北京
    # 格林威治时间 - 19700101 00:0:00 伦敦
    #1564282438.9430697
    #1564282488.7851577
    #时间模块一般用来计算某个程序所用的时间,效率测试
    
    print('start')
    time.sleep(1)
    print('end')
    
    import time
    def func():
    	sum_num = 0
    	for i in range(100000):
    		sum_num += i
    print(time.time())
    func()
    print(time.time())
    
    改进
    import time
    def func():
    	sum_num = 0
    	for i in range(100000):
    		sum_num += i
    start = time.time()
    func()
    print(time.time()-start)
    
1.2 函数进阶
  • 函数名赋值

    def a():
        print('in a func')
    
    a()
    print(a)
    b = a
    print(b)
    b()
    # 并不是只有函数名()才能调用一个函数
    #只要是函数的地址对应的变量都可以通过()调用函数
    l = [a] #a存的是内存地址
    print(l[0]) #这个也是指向a的内存地址
    l[0]() #所以得出的结果还是in a func
    # 实际上函数的名字可以被赋值,也可以作为一个容器类型的元素
    # 变量怎么使用,函数的名字都可以怎么使用
    
  • 函数的名字做参数

    def a():
        print('in a func')
    def wahaha(f):
        print(f)
        f()
    wahaha(a)
    
  • 函数的名字做返回值

    def wahaha():
        def a():
            print('in func a')
        return a
    funca = wahaha() #函数a作为wahaha的返回值赋予给了funca
    funca() #调用funca()就返回了函数a,其中内存地址都指向同一个地方
    
1.3 闭包
  • 闭包:如果一个内部的函数引用了外部函数的变量,那么这个内部函数就是一个闭包函数def wahaha():

       name = 'alex'
        def a():
            #'''一旦内层函数引用了外层函数的变量,a就是一个闭包函数'''
            print('in a func',name)
        return a
    a = wahaha()
    a()
    print(a.__closure__) #a.__closure__不是空元祖,a就是闭包函数,如果没有引用外部变量就打印None
    
    #不是闭包函数,因为inner中没有用到a,b变量
    def func():
        a = 1
        b = 2
        def inner()
            print(1,2)
    
    # inner中虽然用到a,b,但是用到的是自己的参数a,b,而不是外部的变量所以不是闭包
    def func():
        a = 1
        b = 2
        def inner(a,b)
            print(a,b)
    
    def func2():
        a = 1
        b = 2
        def inner():   #是闭包
            print(a,b)
    
    def func2(a,b):
        def inner(): #是闭包
            print(a,b) 
    
    a = 1
    b = 2
    def func2():
        def inner(): #不是闭包
            print(a,b) 
    
  • 闭包的作用:需要把某一个数据存在局部作用域里,既不被污染又能够时时刻刻能重复使用,不用重复创建的时候,使用闭包

    #请求一个网页
    from urllib import request
    # ret = request.urlopen('https://mp.csdn.net/postlist')
    # print(ret.read().decode('utf-8'))
    def get_source_html(url):
        ret = request.urlopen(url)
        return ret.read().decode('utf-8')
    ret = get_source_html('https://www.icourse163.org/')
    print(ret)
    
    #请求一个网页
    from urllib import request
    def get_source_html(url):
        dic = {}
        def get_url():
            if url in dic:
                return dic[url]
            else:
                ret = request.urlopen(url)
                dic[url]=ret
                return ret.read().decode('utf-8')
        return get_url
    get_url = get_source_html('https://www.icourse163.org/')
    print(get_url())
    print(get_url())
    print(get_url())
    
1.4 装饰器
  • 计算函数效率

    # import  time
    # def timmer(funcname):
    #     start = time.time()
    #     funcname()
    #     print(time.time()-start)
    # def func():
    #     sum_num = 0
    #     for i in range(100000):
    #         sum_num += i
    # def func2():
    #     sum_num = 0
    #     for i in  range(100000):
    #         sum_num += i
    #
    # timmer(func)
    # timmer(func2)
    
    改进一:
    import  time #用到了闭包,函数作为返回值,函数作为参数
    def timmer(funcname): #funcname就是'func的内存地址'
        def inner(*args,**kwargs):
            start = time.time()
            funcname(*args,**kwargs)
            print(time.time()-start)
        return inner
    
    def func(n,m):
        sum_num = 0
        for i in range(n,m):
            sum_num += i
        print('sum_num:',sum_num)
    def func2():
        sum_num = 0
        for i in  range(100000):
            sum_num += i
        print('in func2',sum_num)
    
    func = timmer(func) #func = inner的内存地址
    func(n = 100000000,m = 20) #想调用func,实际调的inner
    func2 = timmer(func2)
    func2()
    
    改进二:
    import  time #用到了闭包,函数作为返回值,函数作为参数
    def timmer(funcname): #funcname就是'func的内存地址'
        def inner(*args,**kwargs):
            start = time.time()
            ret = funcname(*args,**kwargs)
            print(time.time()-start)
            return ret
        return inner
    
    def func(n,m):
        sum_num = 0
        for i in range(n,m):
            sum_num += i
        return sum_num
    def func2():
        sum_num = 0
        for i in  range(100000):
            sum_num += i
        return sum_num
    
    func = timmer(func) #func = inner的内存地址
    ret = func(100000,20) #想调用func,实际调的inner
    func2 = timmer(func2)
    ret2 = func2()
    print(ret,ret2)
    

    [外链图片转存失败(img-9H85k0ie-1564886425127)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564640440071.png)]

1.5 什么情况下用,不改变代码
  • @timmer能够让函数快速加上装饰器

    import  time #用到了闭包,函数作为返回值,函数作为参数
    def timmer(funcname): #funcname就是'func的内存地址'
        def inner(*args,**kwargs):
            start = time.time()
            ret = funcname(*args,**kwargs)
            print(time.time()-start)
            return ret
        return inner
    
    @timmer #就是func = timmer(func) #func = inner的内存地址
    def func(n,m):
        sum_num = 0
        for i in range(n,m):
            sum_num += i
        return sum_num
    
    @timmer #func2 = timmer(func2) #func2 = inner的内存地址
    def func2():
        sum_num = 0
        for i in  range(100000):
            sum_num += i
        return sum_num
    
    ret = func(100000,20) #想调用func,实际调的inner
    ret2 = func2()
    print(ret,ret2)
    
  • 什么情况下用

    • 在已经写好发版的程序的基础上,需要对一个函数执行前后增加功能的时候

      • 开放封闭原则
        • 开放:对扩展是开放的(增加新功能)
        • 封闭:对修改时封闭(可以修改装饰器,但内部函数不要修改)
    • 有的时候也会写好一些装饰器,加在需要装饰的函数上面

      • login Django框架里也这么用

      • log

        使用场景
        #用户登录
        # def login():
        #     pass
        #
        # @login
        # def lianxi():
        #     pass
        #
        # @login
        # def gaunli():
        #     pass
        #
        # @login
        # def xinsuibi():
        #     pass
        
        #论坛程序
        # def log():
        #     pass
        # 
        # @log
        # def 发布帖子():
        #     pass
        # 
        # @log
        # def 评论():
        #     pass
        
1.6 装饰器的固定格式
def 装饰器的名字(被装饰的函数名func):
    def inner(*args,**kwargs): #wahaha参数也传给inner
        '''在执行被装饰的函数之前要做的事'''
        '''判断是否登录'''
        ret = func(*args,**kwargs) #inner之后传给func
        '''在执行被装饰的函数之后要做的事'''
        '''写log'''
        return ret #调用wahaha返回wahaha的返回值
    return inner #inner没有括号

@装饰器的名字
def wahaha():
    pass
wahaha() #调用wahaha实际上调用的是inner

[外链图片转存失败(img-UyW3EhYv-1564886425128)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564642148031.png)]

  • 函数名.name

    def register(name):
        print('%s注册'%name)
    print([register.__name__])
    
  • 用户登录

    import time
    def wapper(func):
        def inner(*args,**kwargs):
            ret = func(*args,**kwargs)
            t = time.strftime('%Y-%m-%d %H:%M:%S')
            print('在%s[%s]执行了%s函数'%(t,args[0],func.__name__))
            return ret
        return inner
    
    @wapper
    def login(name):
        print('%s登录'%name)
    
    @wapper
    def register(name):
        print('%s注册'%name)
    # print([register.__name__])
    
    login('alex')
    register('alex')
    
  • 将用户登录信息记录到operate.log日志文件里

    import time
    def wapper(func):
        def inner(*args,**kwargs):
            ret = func(*args,**kwargs)
            t = time.strftime('%Y-%m-%d %H:%M:%S')
            with open(r'operate.log',mode='a',encoding='utf-8') as f:
                f.write('\n在%s[%s]执行了%s函数'%(t,args[0],func.__name__))
            return ret
        return inner
    
    @wapper
    def login(name):
        print('%s登录'%name)
    
    @wapper
    def register(name):
        print('%s注册'%name)
    # print([register.__name__])
    
    login('alex')
    register('alex')
    
    改进
    import time
    from functools import wraps
    def wapper(func): #告诉装饰器装饰的是func
        @wraps(func)
        def inner(*args,**kwargs):
            ret = func(*args,**kwargs)
            t = time.strftime('%Y-%m-%d %H:%M:%S')
            with open(r'operate.log',mode='a',encoding='utf-8') as f:
                f.write('\n在%s[%s]执行了%s函数'%(t,args[0],func.__name__))
            return ret
        return inner
    
    @wapper
    def login(name):
        print('%s登录'%name)
    
    @wapper
    def register(name):
        print('%s注册'%name)
    print([register.__name__])
    
    login('alex')
    register('alex')
    
    • 函数的注释(独立的函数都要写注释)

      def func(a,b):
          '''
          函数的注释:这个函数是做什么用的
          :param a: 表示一个参数 int 长方形的宽
          :param b: int 长方形的长
          :return: int 长方形的面积
          '''
          return a+b
         #param 参数 形参
         # args agrguments 实参
         print(func.__doc__)
      
1.7 一个函数被多个装饰器装饰
  • 装饰器越离函数进越放在里面

    def wrapper1(func): #func = inner2
        def inner(*args,**kwargs):
            print('before inner1')
            ret = func(*args,**kwargs)
            print('after inner1')
            return ret
        return inner
    def wrapper2(func): # func = wahaha
        def inner2(*args,**kwargs):
            print('before inner2')
            ret = func(*args,**kwargs)
            print('after inner2')
            return ret
        return inner2
    @wrapper1 #wahaha = wrapper1(inner2) = inner1
    @wrapper2 #wahaha = wrapper2(wahaha) = inner2
    def wahaha():
        print('WAHAHA')
    
    wahaha() #inner1
    

    [外链图片转存失败(img-vd2gKJWR-1564886425130)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564645131061.png)]

  • 记录登录时间逻辑

    # timmer 装饰器 计算被装饰的函数的执行时间
    # login装饰器 检测被装饰的函数是不是登录,如果没有登录要先登录才能使用这个函数
    # timmer 装饰器永远紧贴着被装饰的函数
    # login 装饰器 没有特殊需求可以任意排列
    # logger 装饰器 没有特殊需求可以任意排列
    
    @login
    @timmer #所以timmer贴近函数
    def get_html():
        pass
    # 先判断登录
    #如果没登录
        #调用登录 input() #输入20s
    # 如果登录了
        # get_html --被装饰的函数
    # 先记录当前时间 = 登录 + get_html
    #get_html()
    #记录结束时间
    
1.8 带参数的装饰器
  • 计算时间

    报错,以后修正
    '''
    /usr/bin/env python
    -*- conding:utf-8 -*-
    ----gongjinmin----
    '''
    
    # 带参数的装饰器
    # flask框架中 路由里用到了带参数的装饰器
    import time
    flag = False
    def timmer(flag): #flag = True
        def outer(func): # func =wahaha
            def inner(*args,**kwargs):
                if flag:
                    start = time.time()
                    ret = func(*args,**kwargs)
                    print(time.time()-start)
                else:
                    ret = func(*args, **kwargs)
                return ret
            return inner
        return outer
    
    @timmer(True) #@outer = wahaha = outer(wahaha)
    def wahaha():
        print('in wahaha')
    
    @timmer
    def wahaha1(flag):
        print('in wahaha1')
    
    @timmer
    def wahaha2(flag):
        print('in wahaha2')
    
    @timmer
    def wahaha3(flag):
        print('in wahaha3')
    
    wahaha()
    wahaha1()
    wahaha2()
    wahaha3()
    
  • 登录改进

    '''
    /usr/bin/env python
    -*- conding:utf-8 -*-
    ----gongjinmin----
    '''
    import time
    from functools import wraps
    def log(filename):
        def wapper(func): #告诉装饰器装饰的是func
            @wraps(func)
            def inner(*args,**kwargs):
                ret = func(*args,**kwargs)
                t = time.strftime('%Y-%m-%d %H:%M:%S')
                with open(filename,mode='a',encoding='utf-8') as f:
                    f.write('\n在%s[%s]执行了%s函数'%(t,args[0],func.__name__))
                return ret
            return inner
        return wapper
    
    @log('login.log')
    def login(name):
        print('%s登录'%name)
    
    @log('register.log')
    def register(name):
        print('%s注册'%name)
    print([register.__name__])
    
    login('alex')
    register('alex')
    

2. 迭代器

  • 迭代器

    # 需要一个从1-100000000的数字序列
    # py2和py3的区别
    #py2 range(100000000)真的在内存中生成100000000个数
        #xrange(100000000) 相当于py3并不是在执行的时候生成100000000个数
    #py3 range(100000000) 并不是在执行的时候生成100000000个数
    
    ran = range(100)
    print(ran)
    #找ran拿数字了
    # ran变成了一个迭代器
    iterator = ran.__iter__() #获取迭代器
    print(iterator)
    print(iterator.__next__())
    print(iterator.__next__())
    print(iterator.__next__())
    #迭代器只记当前的数,获取下一个数就加
    #迭代器能够从一个数据里面一个一个的取值并且这个数据里取出的所有的值在没取之前不占内存
    
  • 迭代器

    1. 一个一个的取值,而不是一次性把所有数据都创建出来,迭代器中的数据不取不创建
    2. 只能按照顺序取,不能跳过也不能回头
    3. 一个迭代器中的数据只能从头到尾取一次
  • 可迭代器:如果一个数据类型中有iter方法,那么这个数据就是可迭代类型

  • 迭代器协议:如果一个数据类型中有iter和next方法,那么这个数据类型就是一个迭代器类型

  • 可迭代器协议包含迭代器协议

    #可迭代的
    print(dir()) #查看方法
    print('__iter__' in dir('abc')) #字符串里有iter方法
    print('__iter__' in dir(123))  #False
    print('__iter__' in dir(123.43)) #False
    print('__iter__' in dir({1,2,3})) #True
    print('__iter__' in dir((1,2,3))) #True
    print('__iter__' in dir({1:3})) #True
    f = open(r'G:\py27\其他脚本\register.log',encoding='utf-8')
    print('__iter__' in dir(f)) #True
    f.close()
    print('__iter__' in dir(range(10))) #True
    
    #迭代器
    print('__next__' in dir('abc')) #False
    #对于基础数据类型来说都不是迭代器,只是可迭代类型
    f = open(r'G:\py27\其他脚本\register.log',encoding='utf-8')
    print('__next__' in dir(f)) #True
    f.close()
    #文件操作符是一个迭代器
    
  • 迭代器的特点:节省内存空间

    • 除了文件操作符以外你见过的所有内容都不是迭代器类型
      都只是可迭代类型

    • 可迭代类型是可以通过某些方法转换成迭代器的

      文件操作符节省空间
      f = open(r'G:\py27\其他脚本\register.log',encoding='utf-8')
      for line in f:
      	print(line) #一行行打印,打印第二行时第一行占用的内存空间会被回收
      f.close()
      
  • 可迭代类型.__iter__方法可以把可迭代类型转换成迭代器

    l = [1,2,3,4,5,6]
    iter = l.__iter__()
    print(iter.__next__())
    print(iter.__next__())
    print(iter.__next__())
    print(iter.__next__())
    print(iter.__next__())
    print(iter.__next__())
    print(iter.__next__())
    
    for循环的基本运行原理
    l = [1,2,3,4,5,6]
    num = l.__iter__()
    while True:
        try:
            print(num.__next__())
        except StopIteration:
            break
    
  • 所有能被for循环的至少是一个可迭代类型

  • 今后如果我说xxx是一个迭代器,知道这个xxx并不是直接存储了内容,而是需要for循环才能获取每一个值

    拿衣服:
    def make_cloth(n):
        clothes = []
        for i in range(n):
            clothes.append('第%s件衣服'%i)
        return clothes
    cloth_lst = make_cloth(100)
    print(cloth_lst)
    
    改进:生成器
    def make_cloth_simple(n):
        '''
        生成器函数,没有return 只有yield
        :param n:
        :return:
        '''
        print('做第一件衣服')
        yield 1
        print('做第二件衣服')
        yield 2
        print('做第三件衣服')
        yield 3
    
    ret =make_cloth_simple(4)
    print(ret) #generator 生成器 生成器 生成器的本质就是一个迭代器
    # print(ret.__next__())
    # print(ret.__next__())
    # print(ret.__next__())
    for i in ret:
    	print(i)
    

3. 生成器

  • 生成器

  • 作用:写生成器函数主要是为了不断的从一个容器里面或一个规则里不断的取需要的一个个数据,既能节省内存又能完成循环或迭代

    def make_cloth_simple(n):
        for i in range(n):
            yield '第%s件衣服'%i #会记住执行到哪里
    ret = make_cloth_simple(10000)
    print(ret)
    for n in range(20):
        print(ret.__next__())
    print('='*50)
    for i in range(50): #接下来在执行会从之前执行的开始
        print(ret.__next__())
    
  • 示例

    #监听文件内的输入
    #在python中监听一个文件的输入事件,只要用户输入了新内容,就打印到屏幕中来
    with open(r'G:\py27\其他脚本\test',mode='r',encoding='utf-8') as f:
        while True:
            ret = f.readline()
            if ret: #如果ret有值
                print(ret) #打印
    改进版:
    def listen():
        with open(r'G:\py27\其他脚本\test',mode='r',encoding='utf-8') as f:
            while True: #可能执行了2000次循环
                ret = f.readline().strip()
                if 'error'in ret: #如果ret有值,可以过滤出error错误日志
                    yield ret #生成器,特点是暂停
    for ret in listen(): #而for只有拿到了真实的值才会打印
        print(ret)
        
    改进:程序写入
    while True:
        with open(r'G:\py27\其他脚本\test',mode='a',encoding='utf-8') as f:
            content = input('>>>')
            f.write(content)
            
    程序读取:
    def listen():
        with open(r'G:\py27\其他脚本\test',mode='r',encoding='utf-8') as f:
            while True: #可能执行了2000次循环
                ret = f.readline().strip()
                if 'error' in ret: #如果ret有值
                    yield ret #生成器,特点是暂停
    for ret in listen(): #而for只有拿到了真实的值才会打印
        print(ret)
    
    

    注意:Linux和Mac不支持手动输入数据再读取,只支持程序输入和程序读取

    [外链图片转存失败(img-dmQ6VDl1-1564886425131)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564721892801.png)]

    # 将来你写的所有的代码 最好都把读文件的操作写成一个生成器
    #代码紧耦合
    def login():
        user = input('username:')
        pwd = input('password:')
        with open(r'G:\py27\其他脚本\test',mode='r',encoding='utf-8') as f:
            for line in f:
                usr,passwd=line.strip().split('|')
                if user == usr and pwd == passwd:
                    print('登录成功')
                    break
            else:
                print('登陆失败')
    login()
    
    #拆分代码思维逻辑
    #登录
    	#读文件
    #注册
    	#检测是不是已经存在相同的用户名	
    一、
    def get_user(file):
        line_lst = []
        with open(file,mode='r',encoding='utf-8') as f:
            for line in f:
                usr,pwd = line.strip().split('|')
                line_lst.append((usr,pwd))
        return line_lst
    
    def login():
        user = input('username:')
        passwd = input('password:')
        for usr,pwd in get_user('test'):
            if usr == user and pwd == passwd:
                print('登录成功')
                break
        else:
            print('登陆失败')
    login()
    
    改进二:
    def get_user(file):
        with open(file,mode='r',encoding='utf-8') as f:
            for line in f:
                usr,pwd = line.strip().split('|')
                yield usr,pwd
    
    def login():
        user = input('username:')
        passwd = input('password:')
        for usr,pwd in get_user('test'):
            if usr == user and pwd == passwd:
                print('登录成功')
                break
        else:
            print('登陆失败')
    login()
    
  • 注意

    • 所有的读文件和写文件 尽量都拆分到其他函数中
    • 不要嵌到你写好的功能函数中
    • 比如 登录 函数中不要写读文件的逻辑
    • 比如 注册 函数中不要写读\写文件的逻辑
  • 生成器:特点:一个生成器中的数据也是只能从头到尾取一次

    def func():
        for i in range(10):
            yield 'a%s'%i
    g = func() #对同一个生成器迭代
    for i in g:
        print(i)
    for i in g:
        print(i)
    结果:
    生成10个数
    
    def func(): 
        for i in range(10):
            yield 'a%s'%i
    for i in func(): #每次生成一个新的生成器迭代
        print(i)
    for i in func():
        print(i)
    结果:
    生成20个数
    
    def func():
        for i in range(10):
            yield 'a%s'%i
    g1 = g2 =func() #还是同一个生成器
    for i in g1:
        print(i)
    for i in g2:
        print(i)
    结果:
    生成10个数
    
    def func():
        for i in range(10):
            yield 'a%s'%i
    g1 = func() #两个生成器
    g2 =func()
    for i in g1:
        print(i)
    for i in g2:
        print(i)
    结果:
    生成20个数
    
3.1 列表推导式
  • 示例

    l = [1,2,3,4,5,6]
    ls = []
    for i in l :
        ls.append(i*2)
    print(ls)
    
    改进
    l = [1,2,3,4,5,6]
    ls = [i*2 for i in l]
    print(ls)
    
    # 所有的偶数都放到新的列表中
    l = [1,2,3,4,5,6]
    ls = [ i for i in l if i%2 == 0]
    print(ls)
    
    # 30以内所有能被3整除的数
    ls = [i for i in range(30) if i%3 == 0]
    print(ls)
    
    #取 100以内的数
    ls = [ i for i in range(100)]
    print(ls)
    
    # 30以内所有能被3整除的数的平方
    ls = [i*i for i in range(30) if i%3 == 0]
    ls = [i**2 for i in range(30) if i%3 == 0]
    print(ls)
    
    # 找到嵌套列表中名字含有两个‘e’的所有名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
    ls = [name for lst in names for name in lst if name.count('e') == 2 ]
    print(ls)
    
3.2 生成器表达式
  • 生成器表达式

    • 列表推导式的[] 换成() 就变成了生成器表达式了

       lst  = [i*2 for i in range(5)]
      print(lst) # lst中的所有元素已经在内存里了
      
      gen = (i*2 for i in range(5))
      print(gen) # gen里什么也没有
      
      ##三种取值方式
      #gen.__next__()
      #for n in gen:pass
      #list(gen)
      
      gen = (i*2 for i in range(5))
      print(gen) 
      print('--->',gen.__next__())
      for i in gen:
          print(i)
      
      #报错StopIteration
      gen = (i*2 for i in range(5))
      print(gen) 
      list(gen) #数字在这里被取完了
      print('--->',gen.__next__())
      for i in gen:
          print(i)
      
      gen = (i*2 for i in range(5))
      print(gen)
      print('--->',gen.__next__())
      print(list(gen))
      for i in gen:
          print(i) 
      
  • 区别:

    • 生成器元素永远需要取才能有不取就没有
    • 列表推导式一旦写好元素就已经在了

4. 总结

  • 迭代器 是一个可以被for循环的节省内存的类型

  • 生成器 是程序员能够自己写的迭代器(生成器本质是迭代器)

    • 生成器函数 yield
      • g = 生成器函数()
    • 生成器表达式
      • g = (表达式)
      • 列表推导式和生成器表达式所使用的的 “表达式是相同的”
  • 所有的生成器都符合迭代器的特点

    • 1.一个一个的取值,而不是一次性把所有数据都创建出来,迭代器中的数据不取不创建
    • 2.只能按照顺序取,不能跳过也不能回头
    • 3.一个迭代器中的数据只能从头到尾取一次
  • 从迭代器中取值的三种方式

    • 1.gen.next
    • 2.for n in gen:pass
    • 3.list(gen)
  • 简单的for循环生成新列表 -->列表推导式联系起来

  • 只要用到列表推导式 --> 把列表推导式转成生成器表达式

  • 生成器函数 --> 处理文件

  • 面试题一 : 生成器函数 + 生成器表达式

    • 生成器中的值只能从头到尾取一次
    def demo():
        for i in range(4):
            yield i
    
    g=demo()
    
    g1=(i for i in g)
    g2=(i for i in g1)
    
    print(list(g1))
    print(list(g2))
    

    [外链图片转存失败(img-MSJD3GHR-1564886425131)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564729498098.png)]

  • 面试题二:重点内容 : 生成器 + for循环

    • for循环一定要拆
    • 生成器代码不取值不调用
    def add(n,i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    
    g=test()
    for n in [1,10]:
        g=(add(n,i) for i in g)
    
    print(list(g))
    #解析
    n=1
    n10
    g = (add(n,i) for i in add(n,i) for i in test())
    g = (add(n,i) for i in add(n,i) for i in (0,1,2,3))
    g = (add(n,i) for i in (10,11,12,13))
    g = (20,21,22,23)
    

    [外链图片转存失败(img-wvZLd2GF-1564886425132)(C:\Users\贡金敏\AppData\Roaming\Typora\typora-user-images\1564729791765.png)]

5. 匿名函数

5.1 三元运算符
  • 示例

    a = 10
    b = 15
    max_num = 0
    if a>b:
        max_num = a
    else:
        max_num = b
    max_num = a if a>b else b
    print(max_num)
    
  • 匿名函数:

    • 如果一个函数中的功能非常小,只有一句代码
    • 这个时候我们就可以把这个函数创建成一个匿名函数
    • lambda表达式 == 匿名函数 (所有匿名函数用lambda表达)
    def func1(a,b):
        return a+b
    ret1 = func1(1,2)
    print(ret1)
    
    匿名函数:
    func2 = lambda a,b:a+b
    ret2 = func2(3,4)
    print(ret2)
    
    def func1(a,b):
        return a+b
        
    func2 = lambda a,b:a+b
    
    print(func1.__name__)
    print(func2.__name__)
    结果:
    func1
    <lambda> 
    
  • 简单到一句话可以描述清楚才用lambda表达式

    lambda表达式 a,b两个值,求比较大的值
    lambda表达式 a为参数,求a的奇\偶性
    lambda表达式 a为参数,求a的绝对值
    
    func1 = lambda a,b : a if a>b else b
    ret = func1(10,2)
    print(ret)
    
    func2 = lambda a : '偶数' if a%2 == 0 else '奇数'
    ret = func2(11)
    print(ret)
    
    func3 = lambda a:a if a>0 else -a
    ret = func3(-2)
    print(ret)
    ret = func3(6)
    print(ret)
    
    func = lambda :2+3+4 #不传参,比较少见,lambda没有return
    ret = func()
    print(ret)
    

6. 递归函数

g)

print(list(g))
#解析
n=1
n10
g = (add(n,i) for i in add(n,i) for i in test())
g = (add(n,i) for i in add(n,i) for i in (0,1,2,3))
g = (add(n,i) for i in (10,11,12,13))
g = (20,21,22,23)


[外链图片转存中...(img-wvZLd2GF-1564886425132)]

### 5. 匿名函数

#### 5.1 三元运算符

* 示例

a = 10
b = 15
max_num = 0
if a>b:
max_num = a
else:
max_num = b
max_num = a if a>b else b
print(max_num)


* 匿名函数:

* 如果一个函数中的功能非常小,只有一句代码
* 这个时候我们就可以把这个函数创建成一个匿名函数
* lambda表达式 == 匿名函数 (所有匿名函数用lambda表达)

def func1(a,b):
return a+b
ret1 = func1(1,2)
print(ret1)

匿名函数:
func2 = lambda a,b:a+b
ret2 = func2(3,4)
print(ret2)


def func1(a,b):
return a+b

func2 = lambda a,b:a+b

print(func1.name)
print(func2.name)
结果:
func1


* 简单到一句话可以描述清楚才用lambda表达式

lambda表达式 a,b两个值,求比较大的值
lambda表达式 a为参数,求a的奇\偶性
lambda表达式 a为参数,求a的绝对值

func1 = lambda a,b : a if a>b else b
ret = func1(10,2)
print(ret)

func2 = lambda a : ‘偶数’ if a%2 == 0 else ‘奇数’
ret = func2(11)
print(ret)

func3 = lambda a:a if a>0 else -a
ret = func3(-2)
print(ret)
ret = func3(6)
print(ret)

func = lambda :2+3+4 #不传参,比较少见,lambda没有return
ret = func()
print(ret)




### 6. 递归函数







以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值