zoukankan      html  css  js  c++  java
  • 装饰器 生成器 进阶

    1.装饰器和函数的一些用法

    from functools import wraps
    def wrapper(func):
        @wraps(func)
        def inner():
            func()
        return inner
    @wrapper
    def func1():
        '''jisfhsdkfkd'''
        print('ddf')
    print(func1.__name__)
    func1()
    print(func1.__doc__)
    
    # def index():
    #     '''这是一个主页信息'''
    #     print('from index')
    #
    # print(index.__doc__)    #查看函数注释的方法
    # print(index.__name__)   #查看函数名的方法
    View Code

    2.装饰器带参数

    FLAG = True
    def out(flag):
        def wrapper(func):
    
            def inner():
                if flag:
                    print(123)
                    func()
                else:
                    func()
            return inner
        return wrapper
    @out(FLAG)
    def func1():
        '''jisfhsdkfkd'''
        print('ddf')
    func1()
    View Code

    3.多层装饰器

    def wrapper1(func):
        def inner1():
            print('wrapper1 ,before func')
            ret = func()
            print('wrapper1 ,after func')
            return ret
        return inner1
    
    def wrapper2(func):
        def inner2():
            print('wrapper2 ,before func')
            ret = func()
            print('wrapper2 ,after func')
            return ret
        return inner2
    
    def wrapper3(func):
        def inner3():
            print('wrapper3 ,before func')
            ret = func()
            print('wrapper3 ,after func')
            return ret
        return inner3
    
    @wrapper3
    @wrapper2
    @wrapper1
    def f():
        print('in f')
        return '哈哈哈'
    
    print(f())
    
    执行结果
    wrapper3 ,before func
    wrapper2 ,before func
    wrapper1 ,before func
    in f
    wrapper1 ,after func
    wrapper2 ,after func
    wrapper3 ,after func
    哈哈哈
    View Code

     4.刷2道题

    # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
    # 要求登录成功一次,后续的函数都无需再输入用户名和密码
    # FLAG = False
    # def login(func):
    #     def inner(*args,**kwargs):
    #         global FLAG
    #         '''登录程序'''
    #         if FLAG:
    #             ret = func(*args, **kwargs)
    #             return ret
    #         else:
    #             username = input('username:')
    #             password = input('password:')
    #             if username == 'boss_gold' and password == '22222':
    #                 FLAG = True
    #                 ret = func(*args,**kwargs)
    #                 return ret
    #             else:
    #                 print('登录失败')
    #     return inner
    # @login
    # def shop_add():
    #     print('增加一件物品')
    # @login
    # def shop_del():
    #     print('删除一件物品')
    # shop_add()
    # shop_del()
    
    
    # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
    def log(func):
        def inner(*args,**kwargs):
            with open('log','a',encoding = 'utf-8') as f:
                f.write(func.__name__ + '
    ')
            ret = func(*args,**kwargs)
            return ret
        return inner
    @log
    def shop_add():
        print('增加一件物品')
    @log
    def shop_del():
        print('删除一件物品')
    shop_add()
    shop_del()
    View Code
    # 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
    # 2.为题目1编写装饰器,实现缓存网页内容的功能:
    # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
    import os
    from urllib.request import urlopen
    def cache(func):
        def inner(*args,**kwargs):
            if os.path.getsize('web_cache'):
                with open('web_cache','rb') as f:
                    return f.read()
            ret = func(*args,**kwargs)
            with open('web_cache','wb') as f:
                f.write(b'***'+ret)
            return ret
        return inner
    
    @cache
    def get(url):
        code = urlopen(url).read()
        return code
    
    ret = get('http://www.baidu.com')
    print(ret)
    
    ret = get('http://www.baidu.com')
    print(ret)
    View Code

    5.从生成器中取值的几个方法

        # next
    # for
    # 数据类型的强制转换 : 占用内存
    def generator():
        for i in range(20):
            yield '哇哈哈%s'%i
    
    g = generator()  #调用生成器函数得到一个生成器
    print(list(g))# 数据类型的强制转换 : 占用内存
    # ret = g.__next__()     #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行
    # print(ret)
    # num = 0
    # for i in g:
    #     num += 1
    #     if num > 5:
    #         break
    #     print(i)
    View Code

     6 .#生成器函数进阶

    #send 获取下一个值的效果和next基本一致
    #只是在获取下一个值的时候,给上一yield的位置传递一个数据
    #使用send的注意事项
    # 第一次使用生成器的时候 是用next获取下一个值
    # 最后一个yield不能接受外部的值
    def generator():
        print(123)
        content = yield 1
        print(content)
        print(456)
        yield 2
        print(789)
    
    g = generator()
    print(g.__next__())
    print(g.send('hello'))
    print(g.send('hello'))
    View Code

    7.计算移动平均值

    def average():
       sum = 0
       count = 0
       avg = 0
       while 1:
           num = yield avg
           sum = sum + num
           count += 1
           avg = sum/count
    
    avg_g = average()
    avg_g.__next__()
    avg1 = avg_g.send(10)
    # avg1 = avg_g.send(50)
    
    
    print(avg1)
    View Code

    计算移动平均值---预激协程的装饰器

    #这个装饰器的目的就是提前激活程序g.__next__()
    #方便客户计算的时候不用再执行g.__next__()
    # def init(func):   #装饰器
    #     def inner(*args,**kwargs):
    #         g = func(*args,**kwargs)    #g = average()
    #         g.__next__()
    #         return g
    #     return inner
    #
    # @init
    # def average():
    #     sum = 0
    #     count = 0
    #     avg = 0
    #     while True:
    #         num = yield avg
    #         sum += num    # 10
    #         count += 1    # 1
    #         avg = sum/count
    #
    # avg_g = average()   #===> inner
    # ret = avg_g.send(10)
    # print(ret)
    # ret = avg_g.send(20)
    # print(ret)
    View Code

    8.yield from

    def generator():
        a = 'adfgg'
        b = 'dskdl'
        for i in a:#两句话相当于==》yield from a
            yield i#两句话相当于==》yield from a
        for i in b:
            yield i
    g = generator()
    for i in g:
        print(i)
    View Code

    9.列表推导式和生成器表达式

    总结:

    1.把列表解析的[]换成()得到的就是生成器表达式

    2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

    3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和: 

    # egg_list = ['鸡蛋%s' %i for i in range(10)]#列表解析
    # print(egg_list)
    # egg_tur = ('鸡蛋%s' %i for i in range(10))#生成器表达式
    # print(egg_tur)
    # print(egg_tur.__next__())
    # print(next(egg_tur)) #next本质就是调用__next__
    # print(egg_tur.__next__())
    
    
    t = sum(x ** 2 for x in range(4))
    print(t)
    s = sum([x ** 2 for x in range(4)])
    print(s)
    m = sum((0,1,4,9))
    print(m)
    print(sum((1,2)))
    View Code
    #[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型]    #遍历之后挨个处理
    #[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件]   #筛选功能
    
    # #30以内所有能被3整除的数
    # print([i for i in range(30) if i%3 == 0])
    # print((i for i in range(30) if i%3 == 0))
    # # 例三:找到嵌套列表中名字含有两个‘e’的所有名字
    # names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
    #          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    # ret = [name for lst in names for name in lst if name.count('e') ==2]
    # # ret = (name for lst in names for name in lst if name.count('e') ==2)
    # print(ret)
    #
    
    #字典推导式
    
    
    # 例一:将一个字典的key和value对调
    # dic = {'a':10,'b':20}
    # dic_reverse = {dic[k]:k for k in dic}
    # print(dic_reverse)
    #
    
    # 例二:合并大小写对应的value值,将k统一成小写
    # d = {'s':10}
    # print(d.get('b',0))
    # print(d.get('s'))
    
    # mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    # s = {k.lower():mcase.get(k.lower(),0) + mcase.get(k.upper(),0) for k in mcase}
    # print(s)
    
    #集合推导式,自带结果去重功能
    
    # s = {x**2 for x in [1,2,-1]}
    # print(s)
    # squared = {x**2 for x in [1, -1, 2]}
    # print(squared)
    
    
    #各种推导式 : 生成器 列表 字典 集合
        #遍历操作
        #筛选操作
    View Code

    10.生成器Generator:

      本质:迭代器,所以拥有__iter__方法和__next__方法

      特点:惰性运算,开发者自定义

    使用生成器的优点:

    1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

     2.提高代码可读性

    print(sum([i for i in range(100)]))#内存占用大,机器容易卡死
    print(sum(i for i in range(100000)))#几乎不占内存
    print(i for i in range(100))#几乎不占内存
    View Code

     11.刷题

    # 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
    
    # def func(filename,s):
    #     with open(filename,encoding = 'utf-8') as f1:
    #         for i in f1:
    #             if s in i:
    #                 yield i
    #
    # g = func('ss','生成器')
    # for i in g:
    #     print(i.strip())
    
    # def check_file(filename,aim):
    #     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
    #         for i in f:
    #             if aim in i:
    #                 yield i
    #
    # g = check_file('1.复习.py','生成器')
    # for i in g:
    #     print(i.strip())
    
    # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
    # def check_file(filename):
    #     with open(filename,encoding='utf-8') as f:   #句柄 : handler,文件操作符,文件句柄
    #         for i in f:
    #             yield '***'+i
    #
    # for i in check_file('1.复习.py'):
    #     print(i.strip())
    def func(filename):
        with open(filename,encoding = 'utf-8') as f1:
            for i in f1:
                yield '***'+i
    
    
    g = func('ss')
    for i in g:
        print(i.strip())
    View Code

     12.生成器表达式面试题

    # 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(g))
    # print(list(g1))
    # print(list(g2))
    
    def add(n,i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    
    g=test()
    # for n in [1,10,5]:
    #     g=(add(n,i) for i in g)
    n = 1
    g=(add(n,i) for i in test())
    n = 10
    g=(add(n,i) for i in (add(n,i) for i in test()))
    n = 5
    g=(15,16,17,18)
    
    
    print(list(g))
    View Code

    13.内置函数

    作用域相关

    基于字典的形式获取局部变量和全局变量

    globals()——获取全局变量的字典

    locals()——获取执行本方法所在命名空间内的局部变量的字典

    # print()
    # input()
    # len()
    # type()
    # open()
    # tuple()
    # list()
    # int()
    # bool()
    # set()
    # dir()
    # id()
    # str()
    
    
    # print(locals())  #返回本地作用域中的所有名字
    # print(globals()) #返回全局作用域中的所有名字
    # global 变量
    # nonlocal 变量
    
    #迭代器.__next__()
    # next(迭代器)
    # 迭代器 = iter(可迭代的)
    # 迭代器 = 可迭代的.__iter__()
    
    # range(10)
    # range(1,11)
    # print('__next__' in dir(range(1,11,2)))
    
    # dir 查看一个变量拥有的方法
    # print(dir([]))
    # print(dir(1))
    
    # help
    # help(str)
    
    # 变量
    # print(callable(print))
    # a = 1
    # print(callable(a))
    # print(callable(globals))
    # def func():pass
    # print(callable(func))
    
    import time
    # t = __import__('time')
    # print(t.time())
    
    # 某个方法属于某个数据类型的变量,就用.调用
    # 如果某个方法不依赖于任何数据类型,就直接调用  —— 内置函数 和 自定义函数
    
    # f = open('1.复习.py')
    # print(f.writable())
    # print(f.readable())
    
    #id
    #hash - 对于相同可hash数据的hash值在一次程序的执行过程中总是不变的
    #     - 字典的寻址方式
    # print(hash(12345))
    # print(hash('hsgda不想你走,nklgkds'))
    # print(hash(('1','aaa')))
    # print(hash([]))
    
    # ret = input('提示 : ')
    # print(ret)
    
    # print('我们的祖国是花园',end='')  #指定输出的结束符
    # print('我们的祖国是花园',end='')
    # print(1,2,3,4,5,sep='|') #指定输出多个值之间的分隔符
    # f = open('file','w')
    # print('aaaa',file=f)
    # f.close()
    
    # import time
    # for i in range(0,101,2):
    #      time.sleep(0.1)
    #      char_num = i//2
    #      per_str = '
    %s%% : %s
    ' % (i, '*' * char_num) 
    #          if i == 100 else '
    %s%% : %s' % (i,'*'*char_num)
    #      print(per_str,end='', flush=True)
    View Code

    14.进度条

    #进度条子
    import time
    for i in range(0,101,2):
         time.sleep(0.1)
         char_num = i//2
         per_str = '
    %s%% : %s
    ' % (i, '*' * char_num) 
             if i == 100 else '
    %s%% : %s' % (i,'*'*char_num)
         print(per_str,end='', flush=True)
    View Code
     
  • 相关阅读:
    Gson简要使用笔记
    android入门到熟练(五)---广播
    95&&96.Unique Binary Search Trees I&&II
    day 08 文件操作
    07 深浅拷贝
    06 day小数据池
    05,.字典,集合
    列表和元组
    字符串
    while 循环,格式化输出和运算编码
  • 原文地址:https://www.cnblogs.com/shangchunhong/p/9228080.html
Copyright © 2011-2022 走看看