Python学习笔记Day04 - 装饰器与生成器

1.装饰器 = 高阶函数+嵌套函数

装饰器:本质是函数,用来装饰其他函数,用来添加额外的功能。

原则:1.不能修改被装饰函数的源代码
      2.不能修改被装饰函数的调用方式

def deco1(func):  # func = bar
    def inner_func(*args, **kwargs):
        print('函数bar前面添加代码')
        i = func(*args, **kwargs)   # 运行原函数bar
        print('函数bar后面添加代码')
        return i    # 返回原函数的返回值
    return inner_func

装饰器的四种情况

  1. 原函数无参数时

     @deco1  # 在原函数前添加deco标记,等效于在调用时使用 bar = deco(bar)
             # 这一步在运行deco函数,将bar重定义
     def bar1():
         ...
    
  2. 原函数有参数时

     @deco1
     def bar2(name, age):
         ...
    
  3. 原函数有返回值

     @deco1
     def bar3():
         print('in the bar3')
         return_bar3 = 'return in bar3'
         return return_bar3
    
     bar2('zhang',18)
     print(bar3())
    
     def deco(job):  # 加参数,添加一层嵌套,其他不变
         def deco2(func):  # func = bar
             def inner_func(*args, **kwargs):
                 print('----------', end='')
                 i = func(*args, **kwargs)
                 print(':', job, end='')
                 print('----------')
                 return i
             return inner_func
         return deco2
    
  4. 装饰函数加参数

     @deco(job='engineer')
     def bar4():
         print('in the bar4', end='')
    
     bar4()
    

装饰器原理

  1. 函数即变量

    • 示范一:

        def foo():
            print('in the foo')
        foo()
      
    • 示范二:bar在foo前

        def bar():
            print('in the bar')
      
        def foo():
            print('in the foo')
            bar()
        foo()
      
    • 示范三:bar在foo后

        def foo():
            print('in the foo')
            bar()
      
        def bar():
            print('in the bar')
        foo()
      
    • 示范四:定义在调用之后

        def foo():
            print('in the foo')
            bar()
        foo()
        def bar():
            print('in the bar')
      
  2. 高阶函数

    a. 把函数名当作一个参数传给另一个函数
    b. 返回值中包含函数名

     # 不改原函数,添加新代码, 是一个简单装饰器
     def bar():
         print('in the bar')
     def test1(func):
         print('-----in the test1-----')
         return func  # 返回函数名
    
     # print(test1(bar))  # 实际上返回的是函数名所代表的内存地址
     bar = test1(bar)  # 将返回的函数名重新定义给bar
     bar()
    
  3. 嵌套函数:在一个函数体内通过def定义另一个函数

2.生成器,迭代器,可迭代对象

可迭代对象:可以用于for循环的对象, Iterable
迭代器:可以被next()函数调用并不断返回下一个值的对象,Iterator

from collections import Iterable, Iterator

print(isinstance([], Iterable))
print(isinstance((x for x in range(10)), Iterator))

生成器都是迭代器, 但list,dict,str虽然是可迭代对象, 却不是迭代器

iter([])  # 将可迭代对象转换成迭代器

生成器

使用生成器,使函数在执行大量数据的时候,可以先跳出执行命令,不影响其他操作
使用next(),当迭代结束的,抛异常

生成器:只有在调用的时候才会生成相应的数据,不能返回上一组数据,只记住当前位置
生成器只有一个__next__()方法,实际上生成器应用中__next__()方法用到较少,而是通过for来循环它

def fib(max):  # 10
    n, a, b = 0, 0, 1
    while n < max:  # n<10
        yield b     # 生成器在此处跳出函数,返回b
        a, b = b, a + b
        n = n + 1
    return '---done---'  # 异常的时候打印的消息

f = fib(10)
print('干点别的事')
print(f.__next__())     # 走到生成器的下一个yield处
print(f.__next__())
print('再干点别的事')
print(f.__next__())

print("====start loop======")
for i in f:  # 使用for进行迭代,不抛异常,直接结束
    print(i)

g = fib(6)
while True:
    try:
        x = next(g)
        print('g:', x)
    except StopIteration as e:  # 抓迭代结束的异常
        print('Generator return value:', e.value)
        break

生成器的并行

import time

def consumer(name):
    print('%s开始吃包子' % name)
    while True:
        index = yield
        print('%s 吃了%s#包子' % (name, index))


def producer(count):
    c1 = consumer('猪八戒')
    c2 = consumer('孙悟空')
    c1.__next__()   # 取生成器的下一个数据
    c2.__next__()
    print('开始做包子')
    for i in range(count):
        time.sleep(1)
        print('做了两个%d#包子' % (i+1))
        c1.send(i+1)
        c2.send(i+1)
    return
producer(3)

# consumer('猪八戒').__next__()
# consumer('zhang').send('11')

3.内置函数

all([1, 2, 0, 3])   # 全为True
any([1, 2, 0, 3])   # 有一个True

exec(code)          # 执行字符串代码
eval("1,2,3,4")     # 字符串转字典

res = filter(lambda i: i > 5, range(10))  # 筛选出想要的,隐函数lambda不可写复杂语句

res = map(lambda i: i * i, range(10))   # 对值按某种方式进行处理 = [i*i, for i in range(10)]

import functools
res = functools.reduce(lambda x, y: x + y, range(1, 10))  # 逐个取值进行运算,累加

a = frozenset([1, 4, 333, 212, 33, 33, 12, 4])  # 冻结,使集合不可变,相当于元组

print(globals())    # 返回当前程序的所有的变量,以键值对形式表示

pow(2, 3)           # 幂函数
round(1.3231, 3)    # 控制小数位数

a = {1: 3, 2: 2, 3: 1}
sorted(a)           # [1,2,3] 默认将key排序输出
sorted(a.items())   # 字典按key排序,生成的是以每组键值对为tuple的list=[(1, 3), (2, 2), (3, 1)]
sorted(a.items(), key=lambda x: x[1])   # 字典按value排序,x相当于每个tuple

a = [1, 2, 3, 4, 5, 6]
b = ['a', 'b', 'c', 'd']
for i in zip(a, b):  # 拉链 将a,b中的相应项一一对应起来,以tuple输出:(1, 'a')
    print(i)

# import iterator
__import__('_iterator')  # 引用字符串名的模块

4.json、pickle序列化

posted @ 2020-07-04 17:50  Jerome12138  阅读(92)  评论(0编辑  收藏  举报