python 13 days
python 13 days
迭代器
可迭代对象:内部含有__iter__
迭代器:可迭代对象.__iter__()
迭代器:内部含有__iter__且__next__
判断 __iter__ 在不在dir(对象中)
isinstance()
优点:1,节省内存 2,惰性机制。 3,单向不可逆。
for 循坏的机制:
while
pass
可迭代对象
s1 = '123'
for i in s1:
print(i)
1
2
3
内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。
print(dir('123')) # '__iter__'
print('__iter__' in dir([1, 2, 3]))
print('__iter__' in dir({'name':'alex'}))
print('__iter__' in dir({'name'}))
print('__iter__' in dir((1, 2, 3)))
print('__iter__' in dir(1)) # False
print('__iter__' in dir(True)) # False
迭代器?可迭代对象通过.__iter__()可以转换成迭代器,满足迭代器协议。
内部含有__iter__ 且 __next__方法的就是迭代器。
l = [1, 2, 3]
l_obj = l.__iter__()
print(l_obj)
<list_iterator object at 0x000002517A23C5C0>
迭代器的取值两种方法:
方法一:__next__()
print(l_obj.__next__())
print(l_obj.__next__())
print(l_obj.__next__())
print(l_obj.__next__())
方法二:for 循坏
for i in l_obj:
print(i)
print('__next__' in dir(l_obj))
第二种判断方式:
from collections import Iterable
from collections import Iterator
print(isinstance('123', Iterable))
print(isinstance('123', Iterator))
True
False
实际上可迭代对象是不可以一个一个的一次取值的,因为他没有__next__方法。
for 循坏提供一个机制:
1,将可迭代对象转化成迭代器
2,利用——next——进行取值
3,用try异常处理方法防止报错
l = [1, 2, 3, 4, 5]
l_obj = l.__iter__()
while True:
try:
print(l_obj.__next__())
except Exception:
break
1
2
3
4
5
迭代器:
1,节省内存。
2,满足惰性机制。
3,取值过程不可逆(一条路走到黑)。
二、生成器
生成器本质也是迭代器,生成器是自己用Python写的迭代器。
1,通过生成器函数构建。
2,通过生成器推导式构建。
def func1():
print(666)
return 222
ret = func1()
print(ret)
666
222
def func1():
print(11)
print(333)
yield 222
print(666)
yield 777
g_obj = func1() # 生成器对象 generator object
print(g_obj.__next__())
print(g_obj.__next__())
11
333
222
666
777
def cloth1():
for i in range(1,10001):
print('衣服%s' % i)
cloth1()
从1开始计算到一万
衣服9997
衣服9998
衣服9999
衣服10000
def cloth2():
for i in range(1,10001):
yield '衣服%s' % i
g = cloth2()
for i in range(1,51):
print(g.__next__())
衣服1
衣服2
衣服3
衣服4
...衣服50
next 和 send 的用法:
def func1():
count = yield 222
print(count)
yield 777
yield 888
g_obj = func1() # 生成器对象 generator object
print(g_obj.__next__())
print(g_obj.send('wusir'))
222
wusir
777
结论:
1,send 具有next功能。
2,send 可以给上一个yield传值。
3, 第一个取值不能使用send.
4,最后一个yield不会得到send的值。
列表推导式,生成器表达式:
列表推导式:能用列表推导式完成的,用python代码都可以完成。
用一句话构建一个你想要的列表。
优点:简单,稍微难理解。
缺点: 不能用debug。
li = []
for i in range(1, 12):
li.append(i)
print(li)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
li = [i for i in range(1, 12)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[ 变量(加工后的变量) for 变量 in 可迭代对象 ] 遍历模式
li = []
for i in range(1, 12):
li.append('python%s期' % i)
print(li)
['python1期', 'python2期', 'python3期', 'python4期', 'python5期', 'python6期', 'python7期', 'python8期', 'python9期', 'python10期', 'python11期']
li = ['python%s期' % i for i in range(1, 12)]
print(li)
['python1期', 'python2期', 'python3期', 'python4期', 'python5期', 'python6期', 'python7期', 'python8期', '
li = ['alex', 'wusir', 'taibai', 'nvshen', 'ritian']
l2 = [i+'_NB' for i in li]
print(l2)
['alex_NB', 'wusir_NB', 'taibai_NB', 'nvshen_NB', 'ritian_NB']
[ 变量(加工后的变量) for 变量 in 可迭代对象 ] 遍历模式
[ 变量(加工后的变量) for 变量 in 可迭代对象 if 判断] 筛选模式
一百以内所有的偶数:
l1 = [i for i in range(1, 101) if i % 2 == 0]
print(l1)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
..............
帅选100以内所有的奇数:
l2 = [i for i in range(1, 101) if i % 2 == 1]
l2 = [i for i in range(1, 101, 2)]
print(l2)
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41
.............
10以内所有数的平方。
print([i*i for i in range(1, 11)])
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
将100以内所有被三整除的数保留到列表中:
print([i for i in range(1,101) if i % 3 == 0])
g = (i*i for i in range(1, 11))
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51.
...............
列表推导式 简单明了,但是占内存
# 生成器表达式 节省内存,不易看出。
#30以内所有能被3整除的数的平方
print([i*i for i in range(1, 31) if i % 3 ==0])
结果:[9, 36, 81, 144, 225, 324, 441, 576, 729, 900]
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
l3 = [ name for i in names for name in i if name.count('e') == 2]
print(l3)
['Jefferson', 'Wesley', 'Steven', 'Jennifer']