python学习笔记_day04


迭代器

可迭代的数据类型

list, dict, tuple, str, range, set  

可迭代协议

可迭代协议在内部实现了__iter__方法
# 使用 dir() 查看可迭代对象的方法
print(dir(range))

'''
结果为
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__',\
 '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__',\
 '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__',\
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__',\
 '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop'\
 ]
'''

迭代器协议

 迭代器协议在内部实现__iter__方法和__next__方法
# 使用 dir() 查看迭代器的方法
print(range(10).__iter__())
'''
结果为
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__',\
 '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__',\
 '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__',\
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__',\
]
'''

迭代器是如何工作的

可迭代对象.__iter__()        --> 迭代器
next(迭代器) 或者 迭代器.__next__()        --> 从迭代器中取值
li = [1,2,3]

a = li.__iter__()
while True:
    # try..excpt是用来捕捉报错的语句
    try:
        print(next(a))
    except: StopIteration:
        break

判断是否是可迭代的/迭代器

from collections import Iterable,Iterator

a = range(10) 
print(isinstance(a, Iterable)) # 判断a是不是可迭代的 --> True
print(isinstance(a, Iterator)) # 判断a是不是迭代器      --> False

# 将可迭代的转化成迭代器
b = a.__iter__() 
print(isinstance(b, Iterable)) # 判断a是不是可迭代的 --> True
print(isinstance(b, Iterator)) # 判断a是不是迭代器      --> True

生成器

由开发者自定义的迭代器, 称为生成器. 所以生成器就是迭代器

生成器函数

包含yield关键字的函数, 就是生成器函数
# 生成器函数
def G():
    for i in range(10)
        yield i

生成器取值

惰性, 执行一次next取一次值
  • next
# 创建内存地址存放生成器
g = G()

# 每次执行next(g), 执行到下一个yield
print(next(g))  # 结果为0
print(next(g))  # 结果为1
  • for 循环
# 从头到尾遍历, 不遇到break或return不会停止
g = G()
for i in g:
    print(i)
  • list强转
# 强转, 会把所有数据拿到内存中, 浪费内存
g = G()
list(g)
  • 注: 重新生成的生成器会重新取值
# next(g)和next(G())不同

# 对生成器g调用next方法
next(g)

# 每次执行都会通过G()创建一个新的生成器, 对新的生成器调用next方法
next(G())

给生成器传参

关键字: send
用法: g.send(argv)
注意: 因为send是将参数传给最近一个执行完的yield前的变量, 传参前必须先激活生成器, 否侧会报错
激活方法: next(g)
def G():
    ret = 0
    ret1 = yield ret
    ret2 = yield ret1
    ret3 = yield ret2
    # 将传入参数做处理
    ret3 = ret3 + 100
    yidld ret3

# 创建
g = G()
# 激活
print(next(g))              # --> 结果为ret --> 0

# 传参
print(g.send(1))    # --> 将1传给ret1, 结果为0
print(g.send(10))   # --> 将10传给ret2, 结果为10
print(g.send(100))  # --> 将100床给ret3, 结果为200

预激生成器

不需要在代码中执行next(), 使用装饰器实现
def wrapper(func):
    def inner(*args, **kwargs):
        ret = func(*argc, **kwargs)
        ret = next(ret)
        return ret
    return inner

yield from..

yield from 可迭代对象
def G():
    yield from 'AB'
    yield from range(3)

# 等价于
def G():
    for i in 'AB':
        yield i
    for j in range(3):
        yield j

生成器的运用

  • 例1
'''
生产1000件衣服, 先拿200件
'''
# 制造衣服的函数
def G_cloth():
    for i in range(1000):
        yield i

g= G_cloth()
for i in g:
    print i
    # 拿到200就不拿了
    if i == 200:
        break
  • 例2
'''
监听文件输入
'''
import time
# 不断readline, 如果有新内容, 则line.strip()为真, yield返回line.strip
def G_listen():
    with open(file,encoding='utf-8',mode='r') as f:
        while True:
            line = f.readline()
            if line.strip():
                yield line.strip()
            time.sleep(0.1)

g= G_listen():
for line in ret:
    print(g)
  • 例3
'''
计算平均值
'''
def G_avg(num):
    sum = 0
    day = 0
    avg = 0
    while True:
        num = yield avg
        sum = sum + num
        day += 1
        avg = sum/day       

# 创建
g = G_avg()
# 激活
next()

print(g.send(10)) # 结果为10
print(g.send(30)) # 结果为20
print(g.send(50)) # 结果为30
print(g.send(30)) # 结果为30

列表推导式, 生成器表达式, 字典推导式, 集合推导式

    [ 结果  for循环迭代  if判断 ]
  • 列表推导式
l = []
for i in range(10):
    if i%2 == 0:
        l.append(i)
# 等价于
l = [i for i in range(3) if i % 2 == 0]
'''
生成一个完整列表
'''

练习

# 找出名字含有两个'e'的
names = [
    ['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
    ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']
]

ret = [ name for name_list in names for name in name_list if name.count('e') ==2 ]
print(ret)
  • 生成器表达式
def G():
    for i in range(10):
        if i%2 == 0:
            yield i
g = G()
# 等价于
g = (i for i in range(3) if i % 2 == 0)
'''
创建一个生成器
'''
  • 字典推导式
a = ['a','b']
b = (1,2)
dic = {}
for i in range(2):
    dic[a[i]] = b[i]
print(dic)
# 等价于
dic = {dic[a[i]]:b[i] for i in range(2)}

匿名函数

又称为 lambda表达式
用于定义简单逻辑的函数
lambda --> 匿名函数关键字
语法: lambda 参数:返回值
def add(a,b):
    return a+b
# 等价于
ret = lambda a,b:a+b
'''
现在有两个元组(('a'),('b')),(('c'),('d'))
需求: 生成列表[{'a':'c'},{'b':'d'}]
'''
tupleA = (('a'),('b'))
tupleB = (('c'),('d'))
a = zip(tupleA,tupleB)
ret = map(lambda a:{a[0]:a[1]},a)
print(list(ret))

内置函数

所有内置函数


print()

'''
print(*args[,sep=’ ‘,end=’\n’,file=None,flush=False)]
sep 间隔符, 默认为空格
end 结束符, 默认为换行符
file 不填则输出到屏幕, 否则填写文件句柄, 输出到文件
flush 是否立即刷新
'''
# 例1 
print(1,2,3,sep=';')
# 结果为 1;2;3

# 例2
for i in (1,2,3):
    print(i,end=' ')
# 结果为 1 2 3

# 例3
f = open('xx','a')
print(1,2,3,file=f)
# 输出到文件
应用示例: 进度条
for i in range(1,101,2):
    print('%s%%: %s' % (i,('*'*i)),end='',flush=True)

filter() –> 根据条件筛选iterable

语法: filter(func,iterable)
python2x: 返回值为list
python3x: 返回值为迭代器
def func(argv):
    if argv % 2 == 0:
        return True
    else:
        return False
g = filter(func,range(11))
# python2x
# g为 [0,2,4,6,8,10]

# python3x
# 返回值g为迭代器类型
l = [i for i in g]
# l为 [0,2,4,6,8,10]

map() –> 根据条件生成iterable

语法: map(func,iteralbe)
python2x: 返回值为list
python3x: 返回值为迭代器
def a(argv):
    return argv*2
g = map(func, [1,2,3])

# python2x
# g为 [1,4,9]

# python3x
# 返回值g为迭代器类型
l = [i for i in g]
# l为 [1,4,9]

zip() –> 拉链函数

zip(iterable1,iterable2,...)
取长度最小的组成元组, zip返回值为迭代器
g = zip((1,2,3),['a','b','c','d'])

l = [i for i in g]
# l为 [(1,'a'),(2,'b'),(3,'c')]

# 连成字典格式
G_map = map(lambda argv:{argv[1]:argv[0]},g)
for i in G_map:
    print(i)
# 结果为
# {'a':1}
# {'b':2}
# {'c':3}

递归函数

猜你喜欢

转载自blog.csdn.net/yang_kaiyue/article/details/80048299