码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-09-03 02:13:06      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:app   star   os.path   需要   foo   一个   name   targe   use   

  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(rD:\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(rD:\oldboy_python\python基础\day15)

 

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

标签:app   star   os.path   需要   foo   一个   name   targe   use   

原文地址:https://www.cnblogs.com/zhangshuyuan/p/9576381.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!