python基础(4):迭代器、生成器、面向过程编程

  1. 迭代器

  2. 生成器

  3. 面向对线编程

一 迭代器

#1、为何要有迭代器?
对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器

#2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__

#3、什么是迭代器对象?
可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象

文件类型是迭代器对象
open('a.txt').__iter__()
open('a.txt').__next__()


#4、注意:
迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
#常配合for循环使用,我们可以完全不再依赖索引去取值了
dic={'a':1,'b':2,'c':3}
for k in dic:
    print(dic[k])

#for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
#优点:
  - 提供一种统一的、不依赖于索引的迭代方式
  - 惰性计算,节省内存
#缺点:
  - 无法获取长度(只有在next完毕才知道到底有几个值)
  - 一次性的,只能往后走,不能往前退

二 生成器

#只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码

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

a = func()
print(next(a))
# ====>first
# 1
print(next(a))
# ====>second
# 2
print(next(a))
#====>third
# 3

b = func()
for i in b:
    print(i)
# ====>first
# 1
# ====>second
# 2
# ====>third
# 3
# ====>end
# 生成器就是迭代器,__iter__方法返回生成器本身,__next__方法执行到函数下一个yield关键字处

def func2(n):
    for i in range(n):
        yield i

>>> a = func2(4)
>>> b = a.__iter__()
>>> b
<generator object func2 at 0x000001B28DB82410>
>>> a
<generator object func2 at 0x000001B28DB82410>

练习

# 1.使用生成器模拟range(1, 7, 2)
def my_range(start, end, step=1):
    while start < end:
        yield start
        start += step

for i in my_range(1, 7, 2):
    print(i)

# 2. 使用生成器模拟linex系统管道

# cat db.txt | grep 'user'

def get_lines(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        while True:
            line = f.readline()
            if line:
                yield line
            else:
                break


def grep(target, lines):
    result = []
    for line in lines:
        if target in line:
            result.append(line)
    return result

print(grep('user', get_lines('D:\oldboy_python\python基础\day15\db.txt')))

携程函数

def eater(name):
    print('%s start to eat food' % name)
    food_list = []
    while True:
        food = yield food_list
        print('%s get %s ,to start eat' % (name, food))
        food_list.append(food)


e = eater('钢蛋')
print(next(e))
# 钢蛋 start to eat food
# []
print(e.send('包子'))
# 钢蛋 get 包子 ,to start eat
# ['包子']
print(e.send('韭菜馅包子'))
# 钢蛋 get 韭菜馅包子 ,to start eat
# ['包子', '韭菜馅包子']
print(e.send('大蒜包子'))
# 钢蛋 get 大蒜包子 ,to start eat
# ['包子', '韭菜馅包子', '大蒜包子']
# 携程函数的装饰器,利用装饰器函数进行首次next(func)

def init(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        next(res)
        return res
    return wrapper


@init
def eater(name):
    print("%s eat food" % name)
    food_list = []
    while True:
        food = yield food_list
        print("%s star to eat %s" % (name, food))
        food_list.append(food)

g = eater("gangdan")

# 不需要使用next初始化
print(g.send("1"))
print(g.send("2"))
print(g.send("3"))
print(g.send("4"))

携程函数的应用

>>> import os
>>> os.walk('D:\test')        
generator object walk at 0x0000000002ADB3B8

>>> os.walk(r'D:\test')       # 使用r 是让字符串中的符号没有特殊意义,针对的是转义
# 可以用inspect.getgeneratorstate(generator)查看携程的状态
# 练习 实现功能:grep  -rl  'python'  /etc
# 面向过程编程
# 使用装饰器对携程函数初始化
# 函数自上向下进行,通过send自上向下传递参数
# yield向上返回tag,cat函数一旦得到res为True则停止搜索
# grep函数一旦发现pattern则向printer函数send目标路径并修改tag

import os


def init(func):
    def wrapper(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return wrapper


@init
def search(target):
    while True:
        filepath = yield
        g = os.walk(filepath)
        for dirname, _, files in g:
            for file in files:
                abs_path = os.path.join(dirname, file)
                target.send(abs_path)


@init
def opener(target):
    while True:
        filepath = yield
        with open(filepath, 'rb') as f:
            target.send((f, filepath))


@init
def cat(target):
    while True:
        f, abs_path = yield
        for line in f:
            res = target.send((line, abs_path))
            if res:
                break


@init
def grep(pattern, target):
    tag = False
    while True:
        line, abs_path = yield tag
        tag = False
        if pattern.encode('utf-8') in line:
            target.send(abs_path)
            tag = True


@init
def printer():
    while True:
        abs_path = yield
        print(abs_path)


g = search(opener(cat(grep('user', printer()))))
g.send(r'D:\oldboy_python\python基础\day15')

猜你喜欢

转载自www.cnblogs.com/zhangshuyuan/p/9576381.html