zoukankan      html  css  js  c++  java
  • day04

    一、 闭包函数

    一 什么是闭包?

    内部函数包含对外部作用域而非全局作用域的引用
    
    #提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇
    

     示例:

    def outter():
        x=110
        def inner():
            print(x)
        return inner
    
    
    f=outter() #这里是把返回值赋值给f
    f() #然后在用f调用函数

    二 闭包的意义与应用

    #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
    #应用领域:延迟计算(原来我们是传参,现在我们是包起来)

    from urllib.request import urlopen #加载爬虫模块
    def index(url):
        def get():
            return urlopen(url).read()
        return get
    baidu=index('http://www.baidu.com') #传入函数参数
    print(baidu().decode('utf-8'))

    二、 装饰器

    装饰器就是闭包函数的一种应用场景

    开放封闭原则:对修改封闭,对扩展开放

    二 什么是装饰器

    装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
    强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
    装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

    三 装饰器的使用

    一个简单的装饰器案例

    
    
    #inner是闭包函数,通过传值 把外面的index传给inner函数,然后计算时间
    import time

    def timmer(func): #func 就是被装饰对象的内存地址
    # func=index
    #时间闭包函数
    def inner():
    start_time = time.time()
    func()
    stop_time = time.time()
    print('run time is %s' % (stop_time - start_time))
    return inner #把内部函数返回出去,方便外面调用

    @timmer #index=timmer(index) 这里调用方式使把正下方的函数名,传给timmer的参数,并且结果赋值给正下方的函数名 ,相当于调用inner函数,inner是闭包函数
    def index():
    time.sleep(3)
    print("welcome to index page")
    index()

     解决home传参问题

    #inner是闭包函数,通过传值 把外面的index传给inner函数,然后计算时间
    import time
    
    def timmer(func):
        # func=index
    #时间闭包函数
        def inner(*args,**kwargs):  #这里用args 接受所有参数
            start_time = time.time()
            func(*args,**kwargs)  #这原样返回
            stop_time = time.time()
            print('run time is %s' % (stop_time - start_time))
        return inner #把内部函数返回出去,方便外面调用
    
    @timmer #index=timmer(index) 这里调用方式使把正下方的函数名,传给timmer的参数,并且结果赋值给正下方的函数名 ,相当于调用inner函数,inner是闭包函数
    # def index():
    #     time.sleep(3)
    #     print("welcome to index page")
    # index()
    def home(name):
        time.sleep(3)
        print("welcome to home %s page"%(name))
    home('sunkedong')

    带有返回值的装饰器
    #inner是闭包函数,通过传值 把外面的index传给inner函数,然后计算时间
    import time
    
    def timmer(func):
        # func=index
    #时间闭包函数
        def inner(*args,**kwargs):
            start_time = time.time()
            res=func(*args,**kwargs)
            stop_time = time.time()
            print('run time is %s' % (stop_time - start_time))
            return res  #这里的意思是把上面res保存的结果返回出去,在外面需要调用
        return inner #把内部函数返回出去,方便外面调用
    
    @timmer #index=timmer(index) 这里调用方式使把正下方的函数名,传给timmer的参数,并且结果赋值给正下方的函数名 ,相当于调用inner函数,inner是闭包函数
    def index():
        time.sleep(1)
        print("welcome to index page")
        return "index-res"  #存一个测试的返回值
    res=index() #把返回值保存到变量中
    print(res)#打印,下面的home是一样的原理
    @timmer
    def home(name):
        time.sleep(1)
        print("welcome to home %s page"%(name))
        return "home-res"
    res=home('sunkedong')
    print(res)

    用户登录装饰器

    第一步

    import time
    def login(func):
        # func=index
        def inner(*args,**kwargs):
            name=input('username>>').strip()
            pwd=input('password>>').strip()
            if name == "sunkd" and pwd == "sunkd":
                res=func(*args,**kwargs)
                return res
        return inner
    
    @login
    def index():
        time.sleep(1)
        print("login success...")
        print("welcome to index page")
        return "index_ok"
    @login
    def home(name,age):
        time.sleep(1)
        print("login success...")
        print('welcome to %s home page,age is %s '%(name,age))
        return "home_ok"home('sunkd',22)
    index()

    第二步、修复两次登录的bug

    import time
    current_status={'user':None,'login_status':False}
    def login(func):
        # func=index
        def inner(*args,**kwargs):
            #下面是判断登录状态,如果字典有内容,并且为True 那么直接执行函数,否则跳到登录
            if current_status['user'] and current_status['login_status'] == True:
                res = func(*args, **kwargs)
                return res
            else:
                name=input('username>>').strip()
                pwd=input('password>>').strip()
                if name == "sunkd" and pwd == "sunkd":
                    print('login sucess.')
                    #登录成功后,记录状态
                    res=func(*args,**kwargs)
                    current_status['user']=name
                    current_status['login_status']=True
                    return res
        return inner
    
    @login
    def index():
        time.sleep(1)
        print("welcome to index page")
        return "index_ok"
    @login
    def home(name,age):
        time.sleep(1)
        print('welcome to %s home page,age is %s '%(name,age))
        return "home_ok"
    
    index()
    home('sunkd',22)

     三、带参数的装饰器

    import time
    current_status={'user':None,'login_status':False}
    
    def auth(user_type='mysql'): #这里可以定义一个默认参数。后面可以重新赋值。
        # user_type='file'
        def login(func):
            def inner(*args,**kwargs):
                #下面是判断登录状态,如果字典有内容,并且为True 那么直接执行函数,否则跳到登录
                if current_status['user'] and current_status['login_status'] == True:
                    res = func(*args, **kwargs)
                    return res
                if user_type == 'file':
                    u='sunkd'
                    p='sunkd'
                elif user_type == 'mysql':
                    print('mysql auth')
                elif user_type == 'ldap':
                    print('ldap auth')
                else:
                    print('no fount the auth type')
                    exit(2)
                #下面开始用户登录
                name = input('username>>').strip()
                pwd = input('password>>').strip()
                if name == u and pwd == p :
                    print('login sucess.')
                    # 登录成功后,记录状态
                    res = func(*args, **kwargs)
                    current_status['user'] = name
                    current_status['login_status'] = True
                    return res
            return inner
        return login
    #下面返回的其实还是inner的函数
    @auth(user_type='file1')
    def index():
        time.sleep(1)
        print("welcome to index page")
        return "index_ok"
    index()
    
    # #下面这种调用方式比较原始,做为理解使用
    # index=auth(user_type='file')(index) #这里就重新赋值了。会打印file
    # index()

    加多个装饰器

    import time
    current_status={'user':None,'login_status':False}
    
    def timmer(func):
        def inner(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is :[%s]' %(stop_time-start_time))
            return res
    
        return inner
    
    def auth(egine='file'):
        # egine='file'
        def wrapper(func):
            def inner(*args,**kwargs):
                if current_status['user'] and current_status['login_status']:
                    res = func(*args, **kwargs)
                    return res
    
                if egine == 'file':
                    u='egon'
                    p='123'
                elif egine == 'mysql':
                    u = 'egon'
                    p = '123'
                elif egine == 'ldap':
                    u = 'egon'
                    p = '123'
                else:
                    pass
                name = input('username>>:').strip()
                pwd = input('password>>:').strip()
                if name == u and pwd == p:
                    print('login successfull')
                    current_status['user'] = name
                    current_status['login_status'] = True
                    res = func(*args, **kwargs)
                    return res
            return inner
        return wrapper
    
    
    @timmer
    @auth(egine='ldap') #@wrapper #index=wrapper(timmer_inner)
    # @timmer #timmer_inner=timmer(index)
    def index():
        time.sleep(3)
        print('welcome to index page')
        return 123
    
    
    index() #inner()

    三、迭代器

    '''
    1 什么叫迭代:迭代是一个重复过程,每次重复都是基于上一次的结果来的
    2 为什么要用迭代器?

    l=['a','b','c']
    n=0
    while n < len(l):
    print(l[n])
    n+=1


    - 对于序列类型:字符串,列表,元组,可以使用基于索引的迭代取值方式,而对于没有索引的类型,如字典,
    集合、文件,这种方式不再适用,于是我们必须找出一种能不依赖于索引的取值方式,这就是迭代器

    3 可迭代的对象:只要对象内置有__iter__方法,obj.__iter__
    4 迭代器对象:对象既内置有__iter__方法,又内置有__next__,如文件对象
    注意:可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代的对象

    '''
    #可迭代的对象

    # 'hello'.__iter__
    # [1,2].__iter__
    # (1,2).__iter__
    # {'a':1}.__iter__
    # {1,2,3}.__iter__
    #

    #既是可迭代对象,又是迭代器对象

    # open('a.txt','w').__iter__
    # open('a.txt','w').__next__

    # 迭代器对象执行__iter__得到的仍然是它本身

    # dic={'a':1,'b':2,'c':3}
    # iter_dic=dic.__iter__()
    #
    # print(iter_dic.__iter__() is iter_dic)

    # f=open('a.txt','w')
    # print(f is f.__iter__())


    #迭代器对象的用处

    # dic={'a':1,'b':2,'c':3}
    # iter_dic=dic.__iter__()
    
    
    # print(iter_dic.__next__())
    # print(next(iter_dic))
    # print(next(iter_dic))
    # print(next(iter_dic)) #StopIteration
    
    
    # with open('a.txt','r') as f:
    # print(next(f))
    # print(next(f))
    # print(next(f))
    
    
    # l=[1,2,3,4,5]
    # iter_l=l.__iter__()
    # print(iter_l)
    # print(next(iter_l))
    # print(next(iter_l))
    # print(next(iter_l))

    #基于迭代器对象的迭代取值(不依赖索引)

    dic={'a':1,'b':2,'c':3}
    
    iter_dic=dic.__iter__()
    obj=range(1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
    
    # list(obj)
    
    
    # while True:
    # try:
    # i=next(iter_dic)
    # print(i)
    # except StopIteration:
    # break
    #
    
    # for i in dic: #iter_dic=dic.__iter__()
    # print(i)


    '''
    迭代器的优缺点:
    - 优点:
    提供了一种统一的迭代取值方式,该方式不再依赖于索引
    更节省内存

    - 缺点:
    无法统计长度
    一次性的,只能往后走,不能往前退,无法获取指定位置的值
    '''

    from collections import Iterable,Iterator
    
    print(isinstance('hello',Iterable))
    print(isinstance('hello',Iterator))
    四、生成器

    定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会到到一个结果
    该结果就是生成器对象

    #
    # def func():
    # print('===>first')
    # yield 1
    # print('===>second')
    # yield 2
    # print('====>third')
    # yield 3
    #
    #
    # g=func()
    # print(g)

    #生成器本质就是迭代器

    # print(next(g))
    # print(next(g))
    # print(next(g))
    # print(next(g))
    
    
    # print(next(func()))
    # print(next(func()))
    # print(next(func()))
    # for i in g:
    # print(i)
    #
    # for i in g:
    # print(i)
    #
    # for i in g:
    # print(i)
    
    '''

    yield的功能:
    - 为我们提供了一种自定义迭代器的方式
    - 对比return,可以返回多次值,挂起函数的运行状态

    '''

    #自定义功能,可以生成无穷多个值,因为同一时间在内存中只有一个值

    # def my_range(start,stop,step=1):
    # while start < stop:
    # yield start
    # start+=step
    
    
    # g=my_range(1,5,2) #1 3
    # print(next(g))
    # print(next(g))
    # print(next(g))
    # print(next(g))
    # print(next(g))
    #
    # for i in my_range(1,1000000000000000000000000000000000000000000,step=2):
    # print(i)
    
     
    
    
    # tail -f access.log | grep '404'
    # import time
    # def tail(filepath):
    # with open(filepath,'rb') as f:
    # f.seek(0,2)
    # while True:
    # line=f.readline()
    # if line:
    # yield line
    # else:
    # time.sleep(0.2)
    #
    # def grep(pattern,lines):
    # for line in lines:
    # line=line.decode('utf-8')
    # if pattern in line:
    # yield line
    #
    # g=grep('404',tail('access.log'))
    # for line in g:
    # print(line)
    
     


    #yield的表达式形式的应用

    # def eater(name):
    # food_list=[]
    # print('%s 开动啦' %name)
    # while True:
    # food=yield food_list #food=‘骨头’
    # print('%s 开始吃 %s' %(name,food))
    # food_list.append(food)
    #
    # g=eater('alex')
    
    # g.send(None) #next(g)
    # print(g.send('骨头'))
    # print(g.send('shi'))
    
     
    
    # def f1():
    # while True:
    # x=yield
    # print(x)
    #
    # g=f1()
    # next(g)
    # g.send(1)
    # g.send(1)
    # g.close()
    # g.send(1)
    # g.send(1)
    # g.send(1)

    二元表达式

     def my_max(x,y):
        return x if x > y else y

    列表解析 与生成器表达式

    egg_list=[]
    for i in range(10):
        if i >= 3:
            res='egg%s' %i
            egg_list.append(res)
    
    
    names=['egon','alex_sb','wupeiqi','yuanhao']
    
    names=[name.upper() for name in names if not name.endswith('sb')]
    print(names)
    #1、把列表推导式的[]换成()就是生成器表达式
    
    #2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
    >>> chicken=('鸡蛋%s' %i for i in range(5))
    >>> chicken
    <generator object <genexpr> at 0x10143f200>
    >>> next(chicken)
    '鸡蛋0'
    >>> list(chicken) #因chicken可迭代,因而可以转成列表
    ['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
    
    #3、优点:省内存,一次只产生一个值在内存中


  • 相关阅读:
    c++ 11 thread 初试
    java UDP聊天与文件传输
    iOS 基础类解析
    Hadoop HA高可用集群搭建(2.7.2)
    object-c 不定參数的遍历和原理
    9.4 返回更新后的行
    java面向接口编程
    Node.js开发入门—套接字(socket)编程
    shell脚本输出带颜色字体
    shell--read命令
  • 原文地址:https://www.cnblogs.com/sunkedong/p/7599522.html
Copyright © 2011-2022 走看看