半锤木的学习日记之 生成器与装饰器

python学习日记
装饰器:不修改函数的调用方式,但是还在原来的函数基础上添加功能
原则:开放封闭原则
开放:对拓展是开放的
封闭:对修改是封闭的
基础格式
举例:



from functools import wraps #引入别人写好的装饰器

def wrapper(f):
    @wraps(f)		#这个装饰器不会再改原来函数的名字
    def inner(*args,**kwargs):  #定义*args和**kwargs可以输入元组字典
        print('装饰函数之前做的事')
        ret = f(*args,**kwargs)
        print('装饰函数之后做的事')
        return ret
    return inner


@wrapper
def holiday(day):
    print('全体放假%s天'%day)
    return '开心'

ret = holiday(3)
print(ret)
#打印装饰器的函数
print(holiday.__name__)

装饰器作业题:
1、编写装饰器,位多个函数加上认证的功能(用户的账号密码来源于文件)
#要求登录成功一次,后续的函数都无需再输入用户名和密码

from functools import wraps
flag = False
def login(func):
    @wraps(func)
    def inner(*args,**kwargs):
        global flag
        '''登陆程序'''
        if flag:
            ret = func(*args, **kwargs)
            print('登陆成功')
            return ret
        else:
            username = input('username:')
            password = input('password:')
            if username == 'boss_gold' and password == '123':
                flag = True
                ret = func(*args,**kwargs)
                print('登陆成功')
                return ret
            else:
                print('登陆失败')

    return inner

@login
def shoplist_add():
    print('增加一件物品')
@login
def shoplist_del():
    print('删除一件物品')


shoplist_add()
shoplist_del()

2、编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都被调用的函数名称写入文件

def log(func):
    def inner(*args,**kwargs):
        with open('log','a',encoding='utf-8') as f:
            f.write(func.__name__+'\n')
        ret = func(*args,**kwargs)

        return ret
    return inner


@log
def shoplist_add():
    print('增加一件物品')
@log
def shoplist_del():
    print('删除一件物品')

shoplist_add()
shoplist_add()
shoplist_add()
shoplist_add()
shoplist_del()
shoplist_del()

带参数的装饰器
三层装饰器

import time
FLAGE = True
def timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end - start)
                return set
            else:
                ret = func(*args, **kwargs)
                return set
        return inner
    return timmer

@timmer_out(FLAGE)
def wahaha(a):
    time.sleep(a)
    print('aaaa')

@timmer_out(FLAGE)
def erguotou(a):
    time.sleep(a)
    print('eeeee')

wahaha(0.1)
erguotou(0.2)

语法糖:@装饰器函数名 后紧接被装饰的函数

迭代器
tips :print(dir([])) 可以告诉我列表拥有的所有方法pycharm
只要含有__iter__方法的都是可迭代的

迭代器的好处:
从容器类型中一个一个的取值,会把所有的值都取到。
节省内存空间
迭代器并不会在内存中再占用一大块内存,
而是随着循环 每次生成一个
每次next每次给我一个

Iterable 可迭代的 – > iter #只要含有__iter__方法的都是可迭代的
[].iter() 迭代器 – > next #通过next就可以从迭代器中一个一个的取值

迭代器协议和可迭代协议
可以被for循环的都是可迭代的
可迭代的内部都有__iter__方法
只要是迭代器 一定可迭代
可迭代的.iter()方法就可以得到一个迭代器
迭代器中的__next__()方法可以一个一个的获取值

from collections import Iterable
from collections import Iterator
print(isinstance([],Iterator)) #利用isintance判断列表是不是迭代器
print(isinstance([],Iterable))

for
只有 是可迭代对象的时候 才能用for
当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代

生成器:自己写的迭代器
只要含有yeild关键字的函数都是生成器函数
且yeild不能和return共用

def generater():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
#生成器函数:执行之后会得到一个生成器作为返回值

ret = generater()
for i in ret:
    print(i)

# print(ret)
# print(ret.__next__())
# print(ret.__next__())

# 从生成器中取值的几个方法
    # next
    # for
    # 数据类型的强制转换 : 占用内存

g = generator()  #调用生成器函数得到一个生成器
print(list(g))			#数据类型的强制转换,变成list
ret = g.__next__()     #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行
print(ret)
num = 0
for i in g:
     num += 1
     if num > 50:
         break
     print(i)

生成器:send
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一个yield的位置传递一个数据
使用send的注意事项:
第一次使用生成器是是用next获取下一个值
最后一个yield不能接受外部的值
例子:求移动平均值
带装饰器的生成器

def init(func):         #装饰器
    def inner(*args,**kwargs):
        f = func(*args,**kwargs)
        f.__next__()
        return f
    return inner

@init
def average():      #生成器
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num
        count += 1
        avg = sum/count

avg_g = average()
# avg_g.__next__()
avg1 = avg_g.send(10)
print(avg1)
avg1 = avg_g.send(20)
print(avg1)
avg1 = avg_g.send(30)
print(avg1)
avg1 = avg_g.send(40)
print(avg1)
avg1 = avg_g.send(50)
print(avg1)
avg1 = avg_g.send(60)
print(avg1)

python3 中带有一个新的生成器语法form
from:返回a,b中的每一个字符

def gen():
    a = 'abfda'
    b = '2312rfde3'
    yield from a
    yield from b
    
g = gen()
for i in g:
    print(i)

鸡蛋列表 列表推导式
公式 + for i in rang(10


egg_list = ['鸡蛋%s' %i for i in range(10)] #列表推导式
print(egg_list)
#用正常的for循环实现鸡蛋列表
egg_list = []
for i in range(10):
    egg_list.append('鸡蛋%s' %i)
print(egg_list)

生成器表达式
与列表表达式的区别是:括号不一样,返回的值不一样----->几乎不占内存

g = (i for i in range(10))
print(g)
for i in g:
    print(i)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值