Python20-Day04

##########迭代器、生成器和面向过程编程##########

一、迭代器

  迭代器是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值;

l = [1,2,3]
count = 0
while count < len(l):
    print(l[count])
    count+=1

  为何要有迭代器?

    对于序列类型:字符串,列表,元组,可以通过使用索引的方式迭代取出其包含的元素,但是对于字典,集合文件等类型是没有索引的,若还想取出其内部包含的元素,

    就必须使用不依赖于索引的迭代方式---迭代器。

  什么是可迭代对象?

    可迭代的对象指的是内置有__iter__方法的对象,即obj.__iter__,如下:

'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__

  什么是迭代器对象?

    可迭代对象执行obj.__iter__()得到的结果就是迭代器对象

    而迭代器器对象指的是内置有__iter__又内置有__next__方法的对象

    文件类型是迭代器对象:

open('a.txt').__iter__()
open('b.txt').__next__()

  注意:

    迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象。

  迭代器对象的使用

dic={'a':1,'b':2,'c':3}
# iter_dic = dic.__iter__()  #得到迭代器对象,迭代器对象既有__iter__又有__next__。
# print(iter_dic.__iter__() is iter_dic)   #True 迭代器.__iter__()得到的仍然是迭代器本身
# print(iter_dic.__next__())  #等同于next(iter_dic)
# print(iter_dic.__next__())
# print(iter_dic.__next__())
# print(iter_dic.__next__())  #元素迭代完成,会抛出异常StopIteration

#有了迭代器,就可以不依赖索引迭代取值了   需要自己捕捉异常,控制next。
iter_dic = dic.__iter__()
print(iter_dic)
while 1:
    try:
        k = next(iter_dic)
        print(dic[k])
    except StopIteration:
        break

  for循环

dic={'a':1,'b':2,'c':3}
for key in dic:
    print(key,dic[key])
#基于for循环,可以不再依赖索引取值
#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')

print(func())
# g=func()
# print(g)
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))

  生成器就是迭代器

    g.__iter__

    g.__next__

    res = next(g)

    print(res)

  练习题:1、自定义函数模拟range(1,7,2)

#1、自定义函数模拟range(1,7,2)
def my_range(start,stop,step=1):
    while True:
        if start < stop:
            yield start
        start+=step
g = my_range(1,7,2)    #g为生成器  生成器就是迭代器,可以通过迭代器迭代取值
print(next(g))
print(next(g))
print(next(g))
# for i in my_range(1,7,2):  #也可以通过for循环取值
#     print(i)

      2、模拟管道,实现功能:tail -f access.log | grep '404'

import time
def tail(filepath):
    with open(filepath,'rb') as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                yield line
            else:
                time.sleep(0.2)
def grep(parttern,lines):
    for line in lines:
        line = line.decode('utf-8')
        if parttern in line:
            yield line


for line in grep('404',tail('access.log')):
    print(line,end='')

三、yield总结

  #1、把函数做成迭代器

  #2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

四、面向过程编程

  #1、强调:面向过程编程绝对不是用函数编程,面向过程是一种编程思想、思路,而编程思路是不依赖于具体的语言或者语法的。也可以说即使我们不依赖于函数,也可以基于面向过程的思想编写程序

  #2、定义

    面向过程的核心是过程,过程指的是解决问题的步骤,即先干什么后干什么。

    基于面向过程设计程序就好比是设计一条流水线,是一种机械式的思维方式

  #3、优点

    复杂的问题流程化,进而简单化

  #4、缺点

    可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身

  #5、应用

    扩展性要求不高的场景,典型案例Linux内核

##########三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数##########

一、三元表达式、列表推导式、生成器表达式

  1、三元表达式 

name = input('姓名:> ').strip()
res = 'NB' if name == 'alex' else 'TNB'
print(res)

  2、列表推导式

# egg_list = []
# for i in range(1,10):
#     egg_list.append('鸡蛋%s' %i)
# print(egg_list)

egg_list = ['鸡蛋%s' %i for i in range(1,10)]
print(egg_list)

  3、生成器表达式

  #1、把列表推导式的[]换成()就是生成器表达式

chicken = ('鸡蛋%s' %i for i in range(1,5))
print(chicken) #chicken = <generator object <genexpr> at 0x00000000021768E0>

# print(next(chicken))  #鸡蛋1
# print(next(chicken))  #鸡蛋2
# print(next(chicken))  #鸡蛋3

print(list(chicken)) #['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', ]   因为chicken可迭代,因而可以转换成列表

  #2、优点:省内存,一次只产生一个值在内存中

 二、声明式编程练习题

#1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
names=['egon','alex_sb','wupeiqi','yuanhao']

res = [name.upper() for name in names]
print(res)   #['EGON', 'ALEX_SB', 'WUPEIQI', 'YUANHAO']
#2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
names=['egon','alex_sb','wupeiqi','yuanhao']
# res = [name for name in names if 'sb' not in  name]   #以sb结尾的名字过滤掉    res = ['egon', 'wupeiqi', 'yuanhao']
res = [len(name) for name in names if 'sb' not in name]  #[4, 7, 7]
print(res)
#3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
#笨方法
# num_list=[]
# with open('a.txt','r',encoding='utf-8') as f:
#     lines = f.readlines()
#     for line in lines:
#         num_list.append(len(line))
# print(max(num_list))
#声明式方法
with open('a.txt',encoding='utf-8') as f:
    print(max(len(line)for line in f))

三、内置函数

  现阶段需要掌握的:

  divmod

    python divmod()函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b,a % b)

>>> divmod(7,2)
(3, 1)
>>> divmod(8,2)
(4, 0)

  enumerate

    enumerate是用来遍历可迭代容器中的元素,同时通过一个计数器变量记录当前元素所对应的索引值。

#示例:
names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names):
    print(f'{index}: {value}')
#输入如下内容:
0: Bob
1: Alice
2: Guido

    这个循环遍历了name列表的所有元素,并通过增加从零开始的计数器变量为每个元素生成索引。

    enumerate()函数允许为循环自定义起始索引值。enumerate()函数中接收一个可选参数,该参数允许为本次循环中的计数器变量设置初始值。

names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names, 1):
    print(f'{index}: {value}')
1: Bob
2: Alice
3: Guido

   

enumerate是Python的一个内置函数。你应该充分利用它通过循环迭代自动生成的索引变量。
索引值默认从0开始,但也可以将其设置为任何整数。
enumerate函数是从2.3版本开始被添加到Python中的,详情见PEP279。
Python的enumerate函数可以帮助你编写出更加Pythonic和地道的循环结构,避免使用笨重且容易出错的手动生成索引。
为了充分利用enumerate的特性,一定要研究Python的迭代器和数据结构解包功能。

作者:vimiix
链接:https://juejin.im/post/5a31146251882503eb4b4755
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  eval

    功能:将字符串str当成有效的表达式来求值并返回结果。

    参数:

      source : 一个python表达式或者函数compile()返回的代码对象

      globals : 可选,必须是dictionary

      locals : 可选,任意map对象

可以把list,tuple,dict和string相互转化。
#################################################
字符串转换成列表
>>>a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
>>>type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
>>> type(b)
<type 'list'>
#################################################
字符串转换成字典
>>> a = "{1: 'a', 2: 'b'}"
>>> type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
{1: 'a', 2: 'b'}
>>> type(b)
<type 'dict'>
#################################################
字符串转换成元组
>>> a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
>>> type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
>>> type(b)
<type 'tuple'>
原文地址:https://www.cnblogs.com/mrwang1101/p/8109339.html