python函数:迭代器,生成器,推导式

内置函数

filter(函数,可迭代对象)

map(函数,可迭代对象)

sorted(值,key=指定排序规则,reverse=True)

reversed(值)zip(值,值,值)

reduce(函数,可迭代对象)

zip(值,值,值)

迭代器

  1. 可迭代对象

    1. 能够for循环的就是一个可迭代对象
    2. 具有__iter__方法的就是可迭代对象
  2. 迭代器

    在上次停留的位置继续去做一些事情

    lst = ["a","b","c","d","e","f"]
    lst1 = lst.__iter__() #创建了一个迭代器
    print(id(lst)) #查看lst的内存地址
    print(id(lst[0])) #查看lst[0]的内存地址
    print(lst1) #迭代器的内存地址
    print(lst1.__next__) 
    print(list(lst1)) # 将迭代器转换成了一个列表
    结果:
    264140179464
    264139523944
    <list_iterator object at 0x0000003D7FFB0198>
    'a'
    ['a', 'b', 'c', 'd', 'e', 'f']
    

    根据以上代码,迭代器我判断就是开辟新的内存地址,然后指向了原来的那个列表

for循环的本质

lst = [1,2,3,1,4,5,6,7]  #新建一个列表
lst1 = lst.__iter__()  #创建一个迭代器lst1
while True:
    try:
        print(lst1.__next__()) #输出迭代的值
    except:StopIteration #如果遇到这个错误就结束

迭代器在次迭代还是原来那个迭代器

lst = [1,2,3,1,4,5,6,7]  #新建一个列表
lst1 = lst.__iter__()  #创建一个迭代器lst1
print(lst1)
print(lst1.__iter__()) #迭代器在次迭代还是原来的值
结果:
<list_iterator object at 0x00000083C34200B8>
<list_iterator object at 0x00000083C34200B8>

具有__iter__()方法的就是一个可迭代对象

迭代器具有__iter__()__next__()

迭代器一定是一个可迭代对象,但是可迭代对象不一定是一个迭代器

可迭代对象的优点

  1. 方便查找
  2. 使用灵活

可迭代对象的缺点

占内存

迭代器的优点

节省内存–惰性机制

迭代器的缺点

  1. 查找不方便
  2. 使用不灵活
  3. 一次性的
  4. 不能后退

迭代器是Python自己提供的一种节省空间的方式

生成器

生成器的本质就是迭代器

迭代器是Python自带的

生成器是程序猿自己写的

生成器如何编写

  1. 基于函数编写生成器

    def func():
        yield 1
    g = func()
    print(g)
    print(g.__next__())
    print(g.__iter__())
    结果:
    <generator object func at 0x000000B9116A2E60>
    1
    <generator object func at 0x000000F585EF2E60>
    

    yield相当于return

    一个yield对应一个next

    怎么区分迭代器和生成器
    1. 通过内存地址来分辨

      迭代器:<list_iterator object at 0x00000091FE4402B0>

      生成器:<generator object func at 0x00000091FE402E60>

      后面的地址是变化的,只是拿了最前面的做判断

    2. 通过send()方法来分辨

      迭代器没有send()方法

      生成器有send()方法

    生成器节省空间

    时间换空间 :

    空间换时间 :

    当文件或数据量较大时使用生成器

    yield from和yield的区别:

    yield后边的内容整体返回

    yield from将可迭代对象中的元素逐个返回

    推荐使用iter()和next()

  2. 基于推导式

推导式

列表推导

普通模式:

print([i for i in range(10)])
结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

筛选模式:

#[加工后变量 for循环 加工条件]
print([i for i in range(10) if i > 5])
print([i for i in range(10) if i % 2 == 1])
print([i%2 for i in range(10)])

字典推导

普通模式
print({i:i+1 for i in range(10)})
结果:
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
筛选模式
print({i:i+1 for i in range(10) if i == 3})
结果:
{3: 4}

集合推导

普通模式

print({i for i in range(10)})
结果:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

筛选模式

print({i for i in range(10) if i > 5 and i > 7})
结果:
{6}

生成器推导

普通模式

g = (i for i in range(10))
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
结果:
0
1
2
3
4

筛选模式

g = (i for i in range(10) if i - 6 == 2)
print(next(g))
结果:
8

面试必考

第一题:
lst = [lambda x:i for i in range(5)]  #将推导式的地址赋值给Lst   #次行是先执行完for循环,然后去下面接着执行
print(lst)
print([em(1) for em in lst])  # [4,4,4,4,4]   执行一次循环,使用一次em,去调用一次50行,不断调用
第二题:
lst = []
for i in range(5):
    lst.append(lambda x:i)  #添加进去的是每个元素的地址  五次执行完毕,匿名函数的返回值最后是i,由于for循环完的时候I的值是4
print(lst) #每个元素的地址
第三题:
new_lst = []
for em in lst:
    new_lst.append(em(1))  # 调用em()函数就是调用lst里面的地址对应的值,但是em()的返回值是4,所以不论执行多少次,他始终添加的值为4
print(new_lst)  #[4, 4, 4, 4, 4]
第四题:
lst = [lambda :i+1 for i in range(3)]  #lst拿了匿名函数的地址0 1 2的内存地址,返回的值为i+1  i为2
for i in lst:
    print(i)
print({em():em()+1 for em in lst})  #首先此循环会执行三次,因为Lst里面有三个内存地址,但是i的值此时为2,所以返回的就是3:4。因为是字典,字典会存在key值得之后自动赋值新值,所以最后的4是最后一次循环的值
第五题:
g = (lambda x:x+i for i in range(3))  # 惰性  生成器推导需要每次用的时候才会执行,不执行自己永远不会动
print([em(2) for em in g])  # [4,4,4]  #此题我故意给的错误答案,若要看正确的,请看下面的详细分析。
"""
第一次:
[em(2) for em in g]
使用到g,g拿到的是推到器推导到的内存地址,所以去了推到器推导进行分析
此时第一次i的值为0,传递的实参为2,所以返回值x+i的值为2
第二次:
[em(2) for em in g]
使用到g,g拿到的是推到器推导到的内存地址,所以去了推到器推导进行分析
此时第二次i的值为1,传递的实参为2,所以返回值x+i的值为3
第三次:
[em(2) for em in g]
使用到g,g拿到的是推到器推导到的内存地址,所以去了推到器推导进行分析
此时第三次i的值为1,传递的实参为2,所以返回值x+i的值为4
"""


def func():
    for i in range(3):
        yield lambda x:x+i  #yield保存上一次取得地址,下次来了直接Next
g = func() #g拿到的是func的内存地址
print(g)
lst = []
for em in g:
    lst.append(em(2))  #2  3  4
print(lst)

g = [lambda x:x+i for i in range(3)]  #g拿到的是lambda的三个内存地址,此时I的值为2
print([em(2) for em in g])  # [4,4,4]

g = (lambda x:x+i for i in range(10))  # 惰性
print([next(g)(2) for em in range(5)])  #[2, 3, 4, 5, 6]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值