python day 12

 迭代器和生成器                                                                                                                    

1. 复习

(1)情况一

 

结果:

(2)情况二

结果:

 

(3)情况三

结果:

 

装饰器函数:

2.生成器

2.1 生成器函数:

def generator():
    print(1)
    return 'a'
ret = generator()
print(ret)

只要含有yield关键字的函数都是生成器函数,yield不能和return共用且需要写在函数内

def generator():
    print(1)
    yield 'a'
ret = generator()
print(ret)

结果:

<generator object generator at 0x0000000005766410>

注意:生成器函数 : 执行之后会得到一个生成器作为返回值

2.2 ret.__next__()

def generator():
    print(1)
    yield 'a'
ret = generator()
print(ret)
print(ret.__next__())

结果:

<generator object generator at 0x000000000564CA98>
1
a

执行过程:

 

(1)一个迭代

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'
g = generator()
ret=g.__next__()
print(ret)

执行结果:

1
a

(2)二次迭代

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'
g = generator()
ret=g.__next__()
print(ret)
ret=g.__next__()
print(ret)

结果:

1
a
2
b

(3)三次迭代

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'
g = generator()
ret=g.__next__()
print(ret)
ret=g.__next__()
print(ret)
ret=g.__next__()
print(ret)

 结果:

1
a
2
b
c

(4)可以换成for循环:

def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'
g = generator()
for i in g:
    print(i)

 结果同上:

1
a
2
b
c

(5)生成100个娃哈哈,生产一个,处理一个。

def wahaha():
    for i in range(100):
        yield '娃哈哈%s'%i
g = wahaha()
for i in g:
    print(i)

 只打印前50个:   

def wahaha():
    for i in range(100):
        yield '娃哈哈%s'%i
g = wahaha()
count = 0
for i in g:
    count += 1
    print(i)
    if count > 50:
        break

打印前50个后还可以接着打印下一个:

def wahaha():
    for i in range(100):
        yield '娃哈哈%s'%i
g = wahaha()
count = 0
for i in g:
    count += 1
    print(i)
    if count > 50:
        break
print(g.__next__())

打印前50个后还可以接着打印50个:

def wahaha():
    for i in range(100):
        yield '娃哈哈%s'%i
g = wahaha()
count = 0
for i in g:
    count += 1
    print(i)
    if count > 50:
        break
for i in g:
    count += 1
    print(i)
    if count > 100:
        break

 与以上区分:

l = [1,2,3,4,5] #可迭代的
#在for形成迭代器 for i in l: print(i) if i == 2: break for i in l: print(i)

执行结果(不是接着第一个执行的):

1
2
1
2
3
4
5

 类似于:

def wahaha():
    for i in range(100):
        yield '娃哈哈%s'%i
g = wahaha()
g1 = wahaha()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g1.__next__())

  结果:

娃哈哈0
娃哈哈1
娃哈哈2
娃哈哈0

监听文件输入的例子 

一边在文件file,中输入,一边输出查看

def tail(filename):
    f = open(filename,encoding='utf-8')
    while True:
        line = f.readline()
        if line.strip():
            yield line.strip()

g = tail('file')
for i in g:
    if 'python' in i:
        print('***',i)

3.装饰器精讲

4.1普通函数的方法和被装饰函数的方法区别

普通函数:

def wahaha():
    '''
    一个打印娃哈哈的函数
    :return:
    '''
    print('娃哈哈')

print(wahaha.__name__) #查看字符串格式的函数名
print(wahaha.__doc__)  #document

被装饰函数:

 

def wrapper(func):  #func = holiday
  def inner(*args,**kwargs): print('在被装饰的函数执行之前做的事') ret = func(*args,**kwargs) print('在被装饰的函数执行之后做的事') return ret return inner @wrapper #holiday = wrapper(holiday) def holiday(day): '''这是一个放假通知''' print('全体放假%s天'%day) return '好开心' print(holiday.__name__) print(holiday.__doc__)

 

被装饰函数执行结果:

inner
None

想正常打印被装饰函数的方法

@wraps(func)带参数的装饰器
from functools import wraps
def wrapper(func):  #func = holiday
    @wraps(func)    
    def inner(*args,**kwargs):
        print('在被装饰的函数执行之前做的事')
        ret = func(*args,**kwargs)
        print('在被装饰的函数执行之后做的事')
        return ret
    return inner

@wrapper   #holiday = wrapper(holiday)
def holiday(day):
    '''这是一个放假通知'''
    print('全体放假%s天'%day)
    return '好开心'

print(holiday.__name__)
print(holiday.__doc__)

 执行结果:

holiday
这是一个放假通知

4.装饰器作业

题目1:

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

 执行代码:

FLAG = False
def login(func):
    def inner(*args,**kwargs):
        global FLAG
        '''登录程序'''
        if FLAG:
            ret = func(*args, **kwargs)  # func是被装饰的函数
            return ret
        else:
            username = input('username : ')
            password = input('password : ')
            if username == 'boss_gold' and password == '22222':
                FLAG = True
                ret = func(*args,**kwargs)      #func是被装饰的函数
                return ret
            else:
                print('登录失败')
    return inner

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

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

shoplist_add()
shoplist_del()
代码

题目2:

# 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_del()
shoplist_del()
shoplist_del()
shoplist_del()
shoplist_del()
执行代码

进阶作业(选做):

# 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

执行代码:

from urllib.request import urlopen
def get(url):
    code = urlopen(url).read()
    return code
ret = get('http://www.baidu.com')
print(ret)

选做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)  #get()
        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)
ret = get('http://www.baidu.com')
print(ret)
执行代码

分成两部分:

5.装饰器进阶内容

 5.1带参数的装饰器

500个函数 

代码:

import time
FLAGE = False
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 ret
            else:
                ret = func(*args, **kwargs)
                return ret
        return inner
    return timmer
# timmer = timmer_out(FLAGE)
@timmer_out(FLAGE)    #wahaha = timmer(wahaha)
def wahaha():
    time.sleep(0.1)
    print('wahahahahahaha')
代码

 5.2多个装饰器装饰一个函数

 推荐书籍:Python核心编程 

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())
例子

 

  

用途:即记录用户的登录情况,又计算这个函数的执行时间

 

 6.作业 

1.默写:带参数的装饰器。需要标注代码的执行步骤。
2.整理作业:函数的知识点以及装饰器相关作业。装饰器作业需要自己写一遍,并给作业加注释。
3.周末大作业:实现员工信息表
文件存储格式如下:
id,name,age,phone,job
1,Alex,22,13651054608,IT
2,Egon,23,13304320533,Tearcher
3,nezha,25,1333235322,IT

现在需要对这个员工信息文件进行增删改查。

不允许一次性将文件中的行都读入内存。
基础必做:
a.可以进行查询,支持三种语法:
select 列名1,列名2,… where 列名条件
支持:大于小于等于,还要支持模糊查找。
示例:
select name, age where age>22
select * where job=IT
select * where phone like 133

 

进阶选做:
b.可创建新员工记录,id要顺序增加
c.可删除指定员工记录,直接输入员工id即可
d.修改员工信息
语法:set 列名=“新的值” where 条件
#先用where查找对应人的信息,再使用set来修改列名对应的值为“新的值”

注意:要想操作员工信息表,必须先登录,登陆认证需要用装饰器完成
其他需求尽量用函数实现

作业要求:
1.今天的第2、3个作业一起打包交上来
2.放在作业2文件夹中
需要交整理的函数相关的思维导图
整理的函数知识点的博客
装饰器作业加注释
3.大作业放在3文件夹中
  文件夹中需要包括:
  代码
  流程图(请上交一张png图片。如果没有合适的画图软件,可以用processon画)
  readme文件(请上交一个txt文件,对作业进行一些简单说明,包括作业的整体思路,如何运行,实现了哪些功能,遇到了哪些问题等。)

 

posted @ 2018-12-04 18:21  李然然  阅读(296)  评论(0编辑  收藏  举报