18_python笔记-迭代器与生成器

文章目录


博客cpen_web

练习1

示例1:实现Python的float功能 将”123.456”转化成浮点数

方法1

def func01(s):
    from functools import reduce
    return reduce(lambda x, y: x + y / (10 ** (len(str(y)))),map(lambda x: int(x),s.split('.')))
print(func01('123.456'))
#注:map(lambda x: int(x),s.split('.'))	保留123 456 的整型

方法2

from functools import reduce
s = "123.456"
s = s.split('.')
print(s)
b = {'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'0':0}
c1 = list(map(lambda i:b.get(i),s[0]))
c2 = list(map(lambda i:b.get(i),s[1]))
def func01(x,y):
    return x*10+y
def func02(x,y):
    return x/10+y
result = reduce(func01,c1) + reduce(func02,c2[::-1])/10
print(result,type(result))

示例2:filter函数:找出[1-100]能被3整除的数

result = filter(lambda x: x%3==0, range(1,101))
print(list(result))

示例3:map函数:求list[1-10]各项的平方

result = map(lambda x: x**2, range(1,11))
print(list(result))

示例4:将列表[1,4,5,9] 转换成 '1459’的字符串

a = [1,4,5,9]
b = "".join(map(str,a))
print(b)

示例5:排序

有以下列表:list1=[7, -8, 5, 4, 0, -2, -5] 正数在前负数在后 正数从小到大 负数从大到小
方法1:元组

# 有以下列表:list1=[7, -8, 5, 4, 0, -2, -5] 正数在前负数在后 整数从小到大 负数从大到小
list1 = [7, -8, 5, 4, 0, -2, -5]
list2 = sorted(list1,key=lambda x:(x<0, abs(x)))    # 注:后面返回的是1个元组
#第一次key函数返回(False,7),(True,8),(False,5),(False,4),(False,0),(True,2),(True,5)
#第一次排序False在前,True在后
#第一个数值相同的时候,再比较第二个
print(list2)
#结果为 [0, 4, 5, 7, -2, -5, -8]

方法2:过滤filter

list1 = [7, -8, 5, 4, 0, -2, -5]
list2 = filter(lambda x: x<0, list1)
list3 = filter(lambda x: x>=0, list1)
list = sorted(list3) + sorted(list2, reverse = True)
print(list)
#结果为 [0, 4, 5, 7, -2, -5, -8]
result=sorted(filter(lambda x:x>=0,list1))+sorted(filter(lambda x:x<0,list1),reverse=True)
print(result)
#结果为 [0, 4, 5, 7, -2, -5, -8]

方法3:数学类方法

list1 = [7, -8, 5, 4, 0, -2, -5]
#7,15,5,4,0,9,12
print(sorted(list1, key = lambda x:max(list1) -x if x<0 else x))
#结果为 [0, 4, 5, 7, -2, -5, -8]

示例6:字符串排序

这是一个字符串排序,排序规则:小写<大写<奇数<偶数
方法:元组

# 这是一个字符串排序,排序规则:小写<大写<奇数<偶数
s = 'asdf234GDSdsf23'		# 注:后面的条件放前面筛选,True在后,False在前
s2 = "".join(sorted(s, key=lambda x: (x.isdigit(),x.isdigit() and int(x) % 2 == 0,x.isupper(),x)))
print(s2)       # 注:先判断是否是数字,判断是否偶数,判断是否大写
#对于a 返回(False,False,False,a)
#对于2 返回(True ,True ,False,2)
#对于G 返回(False,False,True ,G)
#对于3 返回(True ,False,False,3)
#结果为 addffssDGS33224

知识点2 字典排序

示例

>>> a = {"b":2,"c":4,"a":5,"d":3}
>>> sorted(a)						# 注:字典排序,默认输出为key
['a', 'b', 'c', 'd']
>>> sorted(a.values())				# 注:对value值进行排序
[2, 3, 4, 5]
>>> sorted(a.items(), key = lambda x:x[1])		# 注:最后输出为字典,需要转换成元组
[('b', 2), ('d', 3), ('c', 4), ('a', 5)]			# 注:x[1]value值,对value值进行排序
>>> dict(sorted(a.items(), key = lambda x:x[1]))	# 注:x[0]也可以对Key值进行排序
{'b': 2, 'd': 3, 'c': 4, 'a': 5}

知识点3 Python推导式

Python推导式
推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持:
·列表(list)推导式
·字典(dict)推导式
·集合(set)推导式

知识点4 Python推导式-列表(list)推导式

·列表(list)推导式
用[]生成list
基本格式:variable = [out_exp_res for out_exp in input_list if out_exp == 2]

·out_exp_res: 列表生成元素表达式,可以是有返回值的函数。
·for out_exp in input_list: 迭代input_list将out_exp传入out_exp_res表达式中。
·if out_exp == 2: 根据条件过滤哪些值

示例1:打印30以内能被3整除的数,放到1个列表里面

#列表推导式
#打印30以内能被3整除的数,放到1个列表里面
#之前的2种方法
li = []
for i in range(31):
    if i%3 == 0:
        li.append(i)
print(li)
#结果为 [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
print(list(filter(lambda x:x%3==0,range(31))))
#结果为 [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

#列表推导式
print([i for i in range(31) if i%3 == 0])
#for循环 --> if过滤 --> [i]
#跟三元运算有点像
#结果为 [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

示例2:30以内能被3整除的数的平方

#30以内能被3整除的数的平方
print([i**2 for i in range(31) if i%3 == 0])
#结果为 [0, 9, 36, 81, 144, 225, 324, 441, 576, 729, 900]
#i**2 是最终要放在列表里的元素

示例3:找出50以内的偶数(不包括50)

#找出50以内的偶数(不包括50)
print([i for i in range(50) if i%2 == 0])
#结果为 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48]

练习5 推导式嵌套

题目1 找到嵌套列表中名字含有2个’e’的所有名字

names = [[‘Tom’, ‘Billy’, ‘Jefferson’, ‘Andrew’, ‘Wesley’, ‘Steven’, ‘Joe’],
[‘Alice’, ‘Jill’, ‘Ana’, ‘Wendy’, ‘Jennifer’, ‘Sherry’, ‘Eva’, ‘Elven’]]
示例

names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
        ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva', 'Elven']]
print([ name for lst in names for name in lst if name.count("e")>=2 ])
#结果为 ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
#相当于 for --> lst --> for --> name --> if
li = []
for lst in names:
    for name in lst:
        if name.count("e") >= 2:
            li.append(name)
print(li)
#结果为 ['Jefferson', 'Wesley', 'Steven', 'Jennifer']

题目2 100以内能被3整除的数,如果是1个偶数,就取0,如果是奇数,就取这个数

示例

#100以内能被3整除的数,如果是1个偶数,就取0,如果是奇数,就取这个数
#三元运算与列表推导式
print([ 0 if i%2==0 else i for i in range(101) if i%3==0 ])

#后面的if是过滤数据的,前面的是它返回的数据

#布尔值判断
print([i if i % 2 else 0 for i in range(100) if not i%3 ])
#not i%3 被3整除为0 not 0 为True
#结果为 [0, 3, 0, 9, 0, 15, 0, 21, 0, 27, 0, 33, 0, 39, 0, 45, 0, 51, 0, 57, 0, 63, 0, 69, 0, 75, 0, 81, 0, 87, 0, 93, 0, 99]

#等式判断
print([i if i%2!=0 else 0 for i in range(100) if i%3==0])
#结果为 [0, 3, 0, 9, 0, 15, 0, 21, 0, 27, 0, 33, 0, 39, 0, 45, 0, 51, 0, 57, 0, 63, 0, 69, 0, 75, 0, 81, 0, 87, 0, 93, 0, 99]

#等价于
li = []
for i in range(100):
    if i%3 == 0:
        if i%2 == 0:
            li.append(0)
        else:
            li.append(i)

知识点6 Python推导式-字典(dict)推导式

·字典(dict)推导式
字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。
基本格式:variable = {out_key:out_value for out_key,out_value in input_list if out_exp == 2}

·out_key: 返回字典结果的key
·out_value: 返回字典结果的value
·for out_key,out_value in input_list: 迭代input_list将out_exp传入out_exp_res表达式中。
·if out_exp == 2: 根据条件过滤哪些值可以。

示例1

#字典推导式
dict1 = {"a":1,"b":2,"c":3,"d":4,"ac":5}
dict2 = { k:v for k,v in dict1.items() if 'a' not in k }
print(dict2)
#结果为 {'b': 2, 'c': 3, 'd': 4}
#注:key里面不包含'a'的 生成1个新的字典

示例2

#将key转化为小写,合并大小写的key值
#{"a":6,"b":8,"c":4}
dic = {"A":1,"B":2,"c":4,"a":5,"b":6}
print({ k.lower():dic.get(k.lower(),0)+dic.get(k.upper(),0) for k in dic })
#结果为 {'a': 6, 'b': 8, 'c': 4}
#后面是过滤出需要用到的值,前面再去运算
#注:dict获取value建议使用属性get 因为可以指定默认返回值

知识点7 Python推导式-集合(set)推导式

·集合(set)推导式
它们跟列表推导式也是类似的。 唯一的区别在于它使用大括号{}。

·集合推导式,自带去重功能

示例

#集合推导式 --> 去重
lst = [-1,2,1,2,4]
set_li = {i for i in lst}
print(set_li)
#结果为 {1, 2, 4, -1}
#集合特性 天生去重

练习8

·过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
·q1 = [‘a’,‘ab’,‘abc’,‘abcd’,‘abcde’]
·求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
·期望结果:[(0,1),(0,3),(0,5), (2,1), (2,3)…]
·快速更换key和value # 期望结果:{10:‘a’, 34:‘b’}
·q3 = {‘a’: 10, ‘b’: 34}
·合并大小写对应的value值,将k统一成小写 #期望 结果:{‘a’:5, ‘b’:9, ‘c’:3}
·q4 = {‘B’:3, ‘a’:1, ‘b’:6, ‘c’:3, ‘A’:4}

题目1 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母

q1 = [‘a’,‘ab’,‘abc’,‘abcd’,‘abcde’]
示例

q1 = ['a','ab','abc','abcd','abcde']
print([ i.upper() for i in q1 if len(i)>=3 ])
#结果为 ['ABC', 'ABCD', 'ABCDE']

题目2 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表

期望结果:[(0,1),(0,3),(0,5), (2,1), (2,3)…]
示例

#分开写
print([ (i,j) for i in range(6) for j in range(6) if i%2==0 and j%2!=0 ])
#结果为 [(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]

#连在一起写
print([(x,y) for x in range(6) if x%2==0 for y in range(6) if y%2!=0])
#结果为 [(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]

题目3 快速更换key和value

q3 = {‘a’: 10, ‘b’: 34}
期望结果:{10:‘a’, 34:‘b’}
示例

#快速替换key value的值
q3 = {'a': 10, 'b': 34}
print({ k:v for v,k in q3.items() })    # 注:转化成元组
#结果为 {10: 'a', 34: 'b'}

题目4 合并大小写对应的value值,将k统一成小写

q4 = {‘B’:3, ‘a’:1, ‘b’:6, ‘c’:3, ‘A’:4}
期望结果:{‘a’:5, ‘b’:9, ‘c’:3}
示例

q4 = {'B':3, 'a':1, 'b':6, 'c':3, 'A':4}
print({ k.lower():q4.get(k.lower(),0)+q4.get(k.upper(),0) for k in dic})
#结果为 {'a': 5, 'b': 9, 'c': 3}

知识点9 Python可迭代对象

可迭代对象
实现了__iter__方法,该方法返回一个迭代器对象

判断是否为可迭代对象
·dir(b)查看是否实现了__iter__
·使用collections模块的Iterable方法

示例1:判定是不是可迭代对象

#方式1
>>> b = "123"
>>> dir(b)						# 注:查看属性
'__iter__'						# 注:有__iter__方法,那么它就是1个可迭代对象

#方式2:使用collections模块的Iterable方法
>>> b = "123"
>>> from collections import Iterable
>>> isinstance(b, Iterable)				# 注:isinstance判断它是属于什么类
True									# 注:说明它是可迭代对象
>>> isinstance(b, str)					# 注:判断是否属于str类
True
示例2:fp是可迭代对象
[root@cPen_python ~]# cat test
test
test2
test3
test4
[root@cPen_python ~]# fp = open("test")
>>> fp = open("test")
>>> dir(fp)
'__iter__'
>>> from collections import Iterable
>>> isinstance(fp, Iterable)
True

知识点10 Python迭代器(iterator)

迭代器
实现了__iter__和__next__方法 就是1个迭代器
__next__不断的返回下一个值,__iter__方法返回自身

#注:迭代器都是可迭代对象

示例1:获取迭代器对象

>>> a = [1,2,3,4]
>>> dir(a)
['__iter__']		# 注:方法1
>>> b = a.__iter__()    # 注:通过自身的__iter__方法 返回一个迭代器
>>> dir(b)
['__iter__', '__next__']
>>> b.__next__()        # 注:通过迭代器自身的__next__方法不断返回下一个值
1
>>> b.__next__()
2
>>> b.__next__()
>>> a
[1, 2, 3, 4]		# 注:方法2
>>> b = iter(a)         # 注:使用iter 内建函数去返回迭代器
>>> b
<list_iterator object at 0x7f44a6cf8588>
>>> next(b)             # 注:使用内建函数next获取下一个值
1
>>> next(b)
2

示例2:判断迭代器

>>> a = [1,2,3,4]
>>> b = a.__iter__()
>>> dir(b)
'__iter__', '__next__'
>>> from collections import Iterable, Iterator
>>> isinstance(b, Iterable)
True
>>> isinstance(b, Iterator)
True

知识点11 Python迭代器(iterator)

·生成无限序列

示例:生成1个无限序列

>>> from itertools import count
>>> a = count()
>>> type(a)
<class 'itertools.count'>
>>> dir(a)
'__iter__','__next__'
>>> next(a)
0
>>> next(a)
1
>>> next(a)
2
………………
>>> a = count(start=10)				# 注:从10 开始
>>> next(a)
10
>>> next(a)
11
>>> next(a)
12
………………

·从一个有限序列中生成无限序列

示例

>>> from itertools import cycle
>>> import time
>>> weeks = cycle(["星期日","星期一","星期二","星期三","星期四","星期五","星期六"])
>>> print(type(weeks),weeks)
<class 'itertools.cycle'> <itertools.cycle object at 0x7f46296c6f78>
>>> for i in weeks:
...     print(i)
...     time.sleep(1)
... 
星期日
星期一
星期二
星期三
星期四
星期五
星期六
星期日
星期一
星期二
………………

知识点12 Python生成器(genatator)

·什么是生成器-generator
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要手动编写__iter__()和__next__()方法,只需要一个yiled关键字。

·生成器一定是迭代器(反之不成立)
·因此任何生成器也是以一种懒加载的模式生成值

·生成器表达式
·使用()生成generator, 将俩表推导式的[]改成()即可得到生成器。
·列表推导式与生成器表达式,定义和使用非常类似,但是,在(大量数据处理时)性能上相差很大

#注:建议使用生成器
#注:生成器 特殊的迭代器
#1、使用生成器表达式定义生成器
#2、使用yiel关键字定义生成器

示例:使用生成器表达式定义生成器

>>> a = (x for x in range(10**9))			# 注:生成器表达式 不断调用next  不是一次性生成
>>> next(a)
0
>>> next(a)
1
>>> a = [x for x in range(10**9)]			# 注:列表推导式 一次性生成 放到内存

示例:使用生成器表达式定义生成器

>>> a = (x for x in range(0,100))
>>> dir(a)
['__iter__', '__next__']

·yield关键字
包含yield表达式的函数是特殊的函数,叫做生成器函数(generator function),被调用时将返回一个迭代器(iterator),调用时可以使用next或send(msg)
·一个生成器中可以有多个yield
·一旦遇到yield,就会保存当前状态,然后返回yield后面的值
·当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。
·当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。
·yield关键字:保留中间算法,下次继续执行

示例

#2、yield 关键字 --> 生成器函数
#yield不能够定义在外面
#生成器函数 碰到 yield 就返回
def get_content():
    print("this is first yield")
    a = 3
    yield a
    b = 4
    print("this is second yield")
    yield b + 1
    c = 5
    print("this is third yield")
    yield c - 2
    print("end......")

a = get_content()
print(dir(a))   # 注:a是迭代器
print("#########")
print(next(a))
#结果为this is first yield
#3
print("#########")
print(next(a))
#结果为this is second yield
#5
print("#########")
print(next(a))
#结果为this is third yield
#3
print("#########")
print(next(a))
#结果为end......		# 注:报错
print("#########")
# print(next(a))
#使用yield关键字,把普通函数变成生成器

练习13 使用生成器实现斐波那契数列

·yield生成器来实现斐波那契数列

示例

#使用生成器实现斐波那契数列
#1,1,2,3,5,8,13
from itertools import islice
def fib():
    prev, curr = 0, 1
    while True:
        yield curr
        print("curr is :", curr)
        prev, curr = curr, curr+prev
f = fib()
# print(next(f))
# #输出 1
# print(next(f))
# #输出 curr is : 1
# #1
# print(next(f))
# #输出 curr is : 1
# #2
print(list(islice(f,0,10)))
#结果为 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

#注:生成器 惰性求值

练习14 使用递归函数实现斐波那契数列

示例

def feb(n):
    if n == 1 or n == 0:
        return 1
    else:
        return feb(n-1)+feb(n-2)    # feb(2) + feb(1)
print(feb(3))       # 需要feb(2)的出口条件即feb(0)=1
#结果为 3

知识点15 send

·send数据
除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个新的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出生成器。

示例

#send
def counter(start_at = 0):
    count = start_at
    while True:		# 注:send发送的数据会赋值给val,next获取时,val值为None
        val = (yield count)	# 注:yield count默认没有任何返回值,count.send()给它发送返回值
        # print(val)		# 注:val相当于从外部接收的值,如果外部没有收到值,就为None
        if val is not None:
            count = val + 1
        else:
            count += 1
count = counter(5)
print(next(count))
#输出 5
print(next(count))
#输出 6
print(count.send(100))  # 注:返回一个新的值给生成器中的yield count
#输出 101
print(next(count))
#输出 102
count.close()         # 注:关闭一个生成器
print(next(count))    # 注:报错,关闭以后不能再执行了

知识点16 yield from

·yield from

示例

# yield from
def g1(x):
    yield range(x)      # 注:获取1个值range(0,5)
def g2(x):
    yield from range(x) # 注:遍历range里面的值 来获取
it1 = g1(5)
it2 = g2(5)
print( [ x for x in it1] )
#结果为 [range(0, 5)]
print( [ x for x in it2] )
#结果为 [0, 1, 2, 3, 4]

it1 = g1(5)
it2 = g2(5)
print(next(it1))
#结果为 range(0, 5)
# print(next(it1))  # 注:报错 生成器里的东西取完了
print(next(it2))
#结果为 0
print(next(it2))
#结果为 1
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值