Python学习笔记(四,迭代器、生成器、内置函数)

一、迭代器

  1.迭代器定义

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

l = ["aaa","bbb","ccc"]
count = 0
while count< len(l):    #每次重复完成后count都是下一次的初始值
    print(l[count])
    count+=1

  需要迭代器的原因:对于序列类型str、list、tuple可以依赖索引迭代取值,对于dict、set、文件需要提供不依赖索引取值的方式。

  可迭代对象:具有内置__iter__方法的对象。字符串、列表、元组、字典、集合和文件均为可迭代对象。

  迭代器对象:可迭代对象执行obj.__iter__()方法后得到的结果为迭代器对象。迭代器对象内置有__iter__和__next__方法。文件对象为迭代器对象。

  总结

  1.可迭代对象不一定是迭代器对象。

  2.迭代器对象一定是可迭代对象。

  3.调用obj.__iter__()方法,可得到迭代器对象,若本身为迭代器对象,执行该方法得到的仍然是它本身。

  2.迭代器的使用

  可迭代对象调用obj.__iter__()方法得到迭代器对象后,可使用obj.__next__()迭代取值,迭代器对象可直接调用obj.__next__()取值。

  obj.__next__()等同于next(obj),取完值后调用__next__会抛出StopIteration异常。

#每次调用__next__方法取一次值,取完之后再调用该方法会抛出StopIteration异常
l = ["aaa","bbb","ccc"]
iter_list = l.__iter__()
print(iter_list.__next__())
print(iter_list.__next__())
print(iter_list.__next__())
print(iter_list.__next__())

  使用try...except捕获异常

d = {"a":212,"b":111,"c":222}
iter_dict = d.__iter__()
while True:
    try:
        print(next(iter_dict)) #字典迭代取到的为key
    except StopIteration:
        break

  for循环原理

  for k in obj

  a)调用in后的obj__iter=obj.__iter__()得到一个迭代器对象。

  b)  执行k=obj_iter.__next__()将取到的值赋给k,然后执行循环体。

  c)重复过程2,直到捕获到StopInteration异常,结束循环。

  3.迭代器的优缺点

  优点:

    a) 提供一种统一的、不依赖索引的取值方式,为for循环的实现提供了依据。

    b) 迭代器同一时间在内存中只有一个值,更节省内存。

  缺点:

    a) 只能往后取值,为一次性的。

    b) next执行完之前,不能统计值得个数,无获取长度。

二、生成器

  1.生成器定义

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

def func():
    print("1111111111")
    yield 1
    print("2222222222")
    yield 2
    print("3333333333")
    yield 3
g = func()   #g为生成器,生成器就是迭代器
print(next(g))   #func()开始执行到第一个yield,并且打印yield返回值
print(next(g))   #func()执行到第二个yield,并且打印yield返回值
print(next(g))

  yield的功能:

    a) yield提供了一种自定义迭代器的方法

    b) yield于return的区别:yield可以返回多次值,return只能返回一次值。函数暂停与再继续的状态有yield保存。

  模拟管道,实现tail -f access.log | grep "404"

 1 #tail -f access.log|grep "404"
 2 import time
 3 def tail(filepath):
 4     with open(filepath,‘rb‘) as f:
 5         f.seek(0,2)
 6         while True:
 7             line = f.readline()
 8             if line:
 9                 yield line
10             else:
11                 time.sleep(0.05)
12
13 def grep(lines,pattern):
14     for line in lines:   #调用tail后得到生成器对象,可使用for来迭代其中每一行内容
15         line =line.decode(‘UTF-8‘)
16         if pattern in line:
17             yield line
18
19 res = grep(tail("access.log"),"404")  #res也为生成器对象,可使用for来迭代取值
20 for line in res:
21     print(line)

  2.协程函数

  表达式形式的yield,在使用时,第一次必须穿None,g.send(None)等同于next(g)

 1 def eater(name):
 2     print("%s开始吃了"%name)
 3     food_list = []
 4     while True:
 5         food = yield food_list
 6         print("%s吃了%s"%(name,food))
 7         food_list.append(food)
 8
 9 g = eater("xxx")   #创建生成器g
10 res1 = g.send(None)       #初始化yield,拿到返回的空列表
11 print(res1)
12 res2 = g.send("米饭")      #发送"米饭"给yield,继续执行代码到下一个yield,返回列表给res2
13 print(res1)
14 g.close()               #结束迭代
15 res3 = g.send("面条")   #无法发送和获取值
16 print(res3)

  实现功能:grep -rl ‘python‘ /etc

 1 #从某个路径下搜索所有包含某个字符串的文件的路径
 2 import os
 3
 4 def init(func):
 5     def inner(*args,**kwargs):
 6         res = func(*args,**kwargs)
 7         next(res)
 8         return res
 9     return  inner
10
11 #列出某个路径下所有文件的绝对路径
12 @init
13 def list_path(target):
14     while True:
15         file_path = yield
16         g = os.walk(file_path)
17         for pardir,_,files in g:
18             for file in files:
19                 abs_path = "%s\%s"%(pardir,file)
20                 target.send(abs_path)
21
22 #打开某个文件
23 @init
24 def openner(target):
25     while True:
26         abs_path = yield
27         with open(abs_path,"rb") as f:
28             target.send((abs_path,f))
29
30 #读取文件中每一行
31 @init
32 def read_line(target):
33     while True:
34         abs_path,f = yield
35         for line in f:
36             flag = target.send((abs_path,line))
37             if flag:
38                 break
39
40 #从一行中查找某个字符
41 @init
42 def find_str(target,pattern):
43     flag = False                       #用于判断某个文件是否包含有重复的某个字符
44     pattern = pattern.encode("utf-8")
45     while True:
46         abs_path,line = yield flag
47         if pattern in line:
48             target.send(abs_path)
49             flag = True
50
51 #将结果打印出来
52 @init
53 def print_path():
54     while True:
55         abs_path = yield
56         print(abs_path)
57
58 g = list_path(openner(read_line(find_str(print_path(),"abcdef"))))
59 g.send(r"D:\PycharmProjects")

  3.yield总结

  a) 可以把函数做成迭代器

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

三、面向过程编程

  面向过程是一种思路和思想,不依赖于具体的语言或语法,核心思想是过程二字,即按照流水线式分步骤解决问题。

  优点是复杂问题流程化,分解为简单的小功能。

  缺点是可扩展性差,修改流水线任一阶段,会影响到其他阶段。

  适合扩展性要求不高的场景,入linux内核、git、httpd等。

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

  1.三元表达式

name = input(">>:").strip()
res = "SB" if name=="xxx" else "NB"  #满足if条件,则返回if前的值,不满足则返回else后的值
print(res)

  2、列表推导式

l = [str(i)+"xxx" for i in range(1,10)]     #为1-10所有数字添加后缀
print(l)

l = [str(i)+"xxx" for i in range(1,20) if i%2==0]  #1-20所有偶数加后缀
print(l)

  3、生成器表达式

  将列表推导式的[]换为()就是生成器表达式。

#生成老母鸡,需要使用时调用next下蛋
>>> chicken = ("鸡蛋%s"%i for i in range(1,10))
>>> chicken
<generator object <genexpr> at 0x000001AFD64CDF68>
>>> next(chicken)
‘鸡蛋1‘
>>> list(chicken)         #第一个鸡蛋已经下过了,chicken可迭代,因此可转为列表
[‘鸡蛋2‘, ‘鸡蛋3‘, ‘鸡蛋4‘, ‘鸡蛋5‘, ‘鸡蛋6‘, ‘鸡蛋7‘, ‘鸡蛋8‘, ‘鸡蛋9‘]

  4、声明式编程

  a) 将l=[‘xxx‘,‘abc_sb‘,‘aaa‘,‘bbb‘]中的字母全部变大写

l=[‘xxx‘,‘abc_sb‘,‘aaa‘,‘bbb‘]
l = [i.upper()for i in l]
print(l)

  b) 将l=[‘xxx‘,‘abc_sb‘,‘aaa‘,‘bbb‘]中以sb结尾的名字过滤掉,然后保存剩下的名字长度

l=[‘xxx‘,‘abc_sb‘,‘aaa‘,‘bbb‘]
l = [len(i) for i in l if not i.endswith("sb")]
print(l)

  c) 求文件test.txt中最长的行的长度(长度按字符个数算,需要使用max函数)

with open("test.txt",‘r‘,encoding="utf-8") as f:
    res = max(len(line) for line in f)
    print(res)

  d) 求文件test.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

with open("test.txt",‘r‘,encoding="utf-8") as f:
    res = sum(len(line) for line in f)
    print(res)

  生成器只能往后取值,已经取完一次值后,再对生成器做求和结果为0

五、递归和二分法

  1.递归调用定义

  在调用一个函数的过程中,直接或间接调用了该函数本身,称之为递归调用。

  递归调用分为两个阶段:递推和回溯。

  python中使用sys.gettrcursionlimit()查看可递归调用的层数。

import sys
print(sys.getrecursionlimit())  #默认支持1000层递归调用

l=[1,[2,[3,[4,[5,[6,[7,]]]]]]]
def func(l):
    for item in l:
        if type(item) is list:
            func(item)
        else:
            print(item)
func(l)

  2.python中递归调用特点

  python中递归调用效率低,需要在进入下一次递归时保留当前状态。其他语言中有尾递归优化,python中没有,并且对层级做了限制。

  递归使用的要求:

  a) 必须有一个明确的结束条件

  b)  每次进入更深一层递归时,问题规模比上一次有所减少

  c) 递归效率不高,层数过多易导致栈溢出

  3.二分法

 1 l = [2,3,5,6,8,12,15,16,19,22,35,45,56,62,98,122,321]
 2 def binary_search(l,num):
 3     print(l)
 4     mid_index = len(l)//2
 5     if len(l) != 0:
 6         if num < l[mid_index]:
 7             binary_search(l[0:mid_index-1],num)
 8         elif num > l[mid_index]:
 9             binary_search(l[mid_index+1:],num)
10         else:
11             print("find it")
12     else:
13         print("can‘t find %s" % num)
14 binary_search(l,321)

二分法

六、匿名函数

  匿名函数一次性使用,随时随需定义,可应用在max、min、sorted、map、reduce、filter等函数中。

#找出薪水最高的人
salaries = {
    ‘abc‘:3222,
    ‘def‘:111,
    ‘aaa‘:431,
    ‘xxx‘:4133
}
#普通方法
g = zip(salaries.values(),salaries.keys())   #g为迭代器
print(max(g))                  #max按照每次取值的第一个数来比较
#定义函数的方法,打印出薪水最高的人的名字
def func(k):
    return salaries[k]
print(max(salaries,key=func))   #排序是按照key来排序,结果展示按照salaries默认结果展示
#使用匿名函数
print(max(salaries,key=lambda k:salaries[k]))

七、内置函数

  sorted

#薪水排序,输出人名
salaries = {
    ‘abc‘:3222,
    ‘def‘:111,
    ‘aaa‘:431,
    ‘xxx‘:4133
}
print(sorted(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

  map

#给列表中所有元素批量添加后缀
#普通方法
names = [‘xxx‘,‘aaa‘,‘eee‘]
l =[]
for name in names:
    res = "%s_SB"%name
    l.append(res)
print(l)
#使用map添加
g = map(lambda name:‘%s_SB‘%name,names)
print(g)          #g为迭代器
print(list(g))

  filter

#筛选出某个序列中特定元素
names = ["xxx_sb","aaa_sb","sss","ee_sb"]
g = filter(lambda i:i.endswith("sb"),names)
print(g)
print(list(g))

  reduce

#筛选出某个序列中特定元素
#某个序列中连续两个元素进行处理
from functools import reduce
print(reduce(lambda x,y:x+y,range(1,101),100))   #最后的100为初始值,可以不添加。

原文地址:https://www.cnblogs.com/gehan/p/8097450.html

时间: 2024-08-14 02:42:52

Python学习笔记(四,迭代器、生成器、内置函数)的相关文章

13t天 迭代器,生成器,内置函数

上周复习: 函数的递归调用 函数调用时函数嵌套调用的一种特殊形式 函数在调用时,直接或间接调用了自身,就是梯归调用. 直接调用自身 def f1():   print('from f1')   f1()f1() 间接调用函数 def f1():   print('from f1')   f2()?def f2():   print('from f2')   f1()f1() 梯归 递归应该分为两个明确的阶段,回溯与递推. 回溯就是从外向里一层一层递归调用下去,回溯阶段必须要有一个明确地结束条件,

Python学习(十六)内置函数,递归

1.递归 def test1(): num=int(input('输入数字')) if num%2==0: #判断输入数字是不是偶数 return True #是偶数,程序退出,返回true print('不是偶数请重新输入') return test1() #不是偶数的话继续调用自己,输入值 print(test1()) 递归的效率不高,最多递归999次 2.内置函数 python自带的函数 id()#看内存地址type()#看数据类型print()#打印input()#输入list() #转

迭代器 生成器 内置函数

1.迭代器 迭代取值的工具 s = 'hello' n = 0 while n < len(s): print(s[n]) # h e l l o n += 1# 每一次迭代都是基于上一次的结果而来的 能够迭代取值的数据类型:字符串.列表.元组.集合.字典 可迭代对象:只有内置有__iter__方法的都叫可迭代对象 可迭代对象有 str list tuple dict set,文件对象本身就是迭代器对象 可迭代对象执行内置的__iter__方法得到的就是该对象的迭代器对象 迭代器对象:内置__i

python学习笔记(5)--迭代器,生成器,装饰器,常用模块,序列化

生成器 在Python中,一边循环一边计算的机制,称为生成器:generator. 如: 1 >>> g = (x * x for xin range(10)) 2 >>> g3 <generator object <genexpr> at 0x1022ef630> 此处g就是一个生成器. 迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是gene

day5-Python学习笔记(八)内置函数

#函数即变量# len type print input str # print(all([1, 2, 3, 4])) # 判断可迭代的对象里面的值是否都为真# print(any([0, 1, 2, 3, 4])) # 判断可迭代的对象里面的值是否有一个为真# print(bin(100)) # 十进制转二进制# ejz = bin(100)# print(ejz.replace('0b',''))# print(chr(65)) # 打印数字对应的ascii# print(ord('A'))

Python这7个好用内置函数!

这篇文章我们来看几个很有用的 Python 内置函数 ,我认为每个学习 Python的 都应该知道这些函数. 对于每个函数,我会使用一个普通的实现来和内置函数做对比. 如果我直接引用了内置函数的文档,请理解,因为这些函数文档写的非常棒! all(iterable) 如果可迭代的对象(数组,字符串,列表等,下同)中的元素都是 true (或者为空)的话返回 True . _all = True for item in iterable: if not item: _all = False brea

Python学习笔记四(迭代器、生成器、内置函数)

一.迭代器 1.迭代器定义 迭代是一个重复的过程,每次重复一次迭代,并且每次迭代的结果都是下一次迭代的初始值. l = ["aaa","bbb","ccc"] count = 0 while count< len(l): #每次重复完成后count都是下一次的初始值 print(l[count]) count+=1 需要迭代器的原因:对于序列类型str.list.tuple可以依赖索引迭代取值,对于dict.set.文件需要提供不依赖索引取

python学习笔记之生成器和迭代器、内置函数

生成器 迭代器 内置函数 作业 一.生成器 1.1.列表生成器 问题引入:看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1 方案一: a = [1,3,4,6,7,7,8,9,11] for index,i in enumerate(a): a[index] +=1 print(a) 原值修改 方案二: >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> a = map(lambda x:x

python基础篇【第四篇】内置函数、装饰器:

一.内置函数: 对于一些python中常用的函数,python自身就已经定义了一些函数用于调用,我们就叫它内置函数!如以下都是python中内置的函数! 一些常用的内置函数具体用法: 一些常用的内置函数具体用法: 1.abs():取绝对值 1 n=abs(-2) 2 print(n) 3 4 结果: 5 2 2.all();传入可迭代的对象中,都为真才为真; Fasle: 0,None,"",[],{} ,()都为假True: 1,-1,True,有值返回真. n=all([1,2,3

Python学习笔记(四)Python对象类型及其运算

Python对象的相关术语: Python程序中保存的所有数据都是围绕对象这个概念展开的 程序中存储的所有数据都是对象 每个对象都有一个身份,一个类型和一个值 例如,school="MaGe linux"会以"MaGe linux"创建一个字符串对象,其身份是指向它在内存中所处位置的指针(其在内存中的地址),而school就是引用这个具体位置的名称 In [14]: name="herry" In [15]: id(name) Out[15]: