您的位置:首页 > 博客中心 > 互联网 >

函数进阶· 第3篇《常用内置函数filter()、map()、zip(),怎么用的呢?》

时间:2022-05-11 07:34

坚持原创输出,点击蓝字关注我吧

技术图片

作者:清菡
博客:oschina、云+社区、知乎等各大平台都有。

由于微信公众号推送改为了信息流的形式,防止走丢,请给加个星标 ?,你就可以第一时间接收到本公众号的推送!

目录

  • 一、filter()函数
    • 1.filter()过滤序列
    • 2.生成器、迭代器都是可迭代对象
  • 二、map()函数
  • 三、zip()函数
    • 1.什么是 zip()函数
    • 2.zip()可以快速创建字典

常用的内置函数:

  • map()函数:会根据提供的函数对指定序列做映射。
  • filter()函数:函数用于过滤序列。
  • zip()函数:函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组。

一、filter()函数

1.filter()过滤序列

filter:过滤序列。第一参数是函数;第二参数是可迭代对象。

看看filter()这个内置函数的源码:

class filter(object):
    """
    filter(function or None, iterable) --> filter object

    Return an iterator yielding those items of iterable for which function(item)
    is true. If function is None, return the items that are true.
    """
    def __getattribute__(self, *args, **kwargs): # real signature unknown
        """ Return getattr(self, name). """
        pass

    def __init__(self, function_or_None, iterable): # real signature unknown; restored from __doc__
        pass

    def __iter__(self, *args, **kwargs): # real signature unknown
        """ Implement iter(self). """
        pass

    @staticmethod # known case of __new__
    def __new__(*args, **kwargs): # real signature unknown
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass

    def __next__(self, *args, **kwargs): # real signature unknown
        """ Implement next(self). """
        pass

    def __reduce__(self, *args, **kwargs): # real signature unknown
        """ Return state information for pickling. """
        pass

看源码发现居然是个类。

它接收到的是2个参数,2个参数在哪里看呢?

__init__方法里面看。既然是个类,调用的时候创建一个对象。

技术图片

Python 中的可迭代对象在一个模块里面。迭代器、生成器、可迭代对象都在这个模块里面。

from collections import Iterator,Iterable,Generator

生成器属于迭代器,生成器是可迭代对象。

列表是个可迭代对象。filter()这个内置函数传 2 个参数后,会返回出一个对象。

filter()源码可以看出它是个类,调用它给它传参,类返回的结果肯定是个对象。

filter()的作用是过滤,它会进行迭代操作。

它会把后面传入的可迭代对象,里面的元素全部遍历一遍。然后把遍历出来的元素当作参数传到这个fun函数里面。

当前这个fun()函数没有定义参数,这个时候运行看看:

# 内置函数
def fun():
    pass

li = [1,2,122,331,11,22,33,4,6,7,2,88,31]

res=filter(fun,li)
print(list(res))

返回列表的时候报错了,fun()需要 0 个参数,但是这里给了一个参数:

技术图片

当我们把它转换成列表的时候,在这里传进去,它会返回一个对象,这个对象里有一个函数,还有个可迭代对象filter(fun,li)

使用filter()传出来的数据也是个迭代器。它也是个可迭代对象,就可以通过list把它转换成列表。

当你转换的时候,它会把第一个参数拿到,传到fun()里面去,会自动传参的。

技术图片

加个参数,再运行:

# 内置函数
def fun(n):
    pass

li = [1,2,122,331,11,22,33,4,6,7,2,88,31]

res=filter(fun,li)
print(list(res))

运行结果:

技术图片

这个列表是空的。因为函数pass掉了。只写个pass,调用这个函数,返回的值是没有结果的。

filter()会根据传进去的参数,调用func()函数,这个函数根据返回值pass,来确定函数li要不要添加到新的列表里面。

如果将代码修改成这样return True

def fun(n):
    return True

li = [1,2,122,331,11,22,33,4,6,7,2,88,31]

res=filter(fun,li)
print(list(res))

返回结果:

技术图片

返回一个 False:

技术图片

输出结果是一个都没有了。

filter()函数可以过滤,可以写过滤条件。比如要保留n<10的数据要保留下来,n<10是个比较语句。

n<10返回的是个 True(当前传入的参数保留,添加到新的列表里面),n>10返回的是个 False(就把数据去掉不要了):

def fun(n):
    return n<10

li = [1,2,122,331,11,22,33,4,6,7,2,88,31]

res=filter(fun,li)
print(list(res))

技术图片

其实和这段代码的操作是一样一样的:

li1 = []
for i in li:
    if i > 10:
        li1.append(i)

内部操作是这样的:

定义了个新的列表li1,在这里面来了一个for循环,判断i是不是大于 10,如果大于 10,就把它添加到新的列表里面。

会根据你传入的参数fun(n)进行相应的判断和比较。根据函数返回的是True还是None,来决定这个数据要不要保留起来。

2.生成器、迭代器都是可迭代对象

定义个生成器、可迭代对象、迭代器:

from collections import Iterator,Iterable,Generator
def fun(n):
    return n < 10

# 列表就是可迭代对象
li = [1, 2, 122, 331, 11, 22, 33, 4, 6, 7, 2, 88, 31]
res = filter(fun, li)

# 定义个迭代器
# 可以把一个可迭代对象转换成一个迭代器
li2 = iter(li)

# 定义个生成器
li3 = (i for i in range(5))

# 用isinstance 判断下列表是不是个可迭代对象
print(isinstance(li,Iterable))
print(isinstance(li2,Iterable))
print(isinstance(li3,Iterable))

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()

技术图片

返回都是True,所以它们 3 个都是可迭代对象。

生成器属于迭代器,那么生成器也是可迭代对象。迭代器是可迭代对象,但是迭代器不是生成器。

二、map()函数

map()的机制和filter()是一样的。它也会将后面的可迭代对象里面的数据迭代出来,放到第一个函数里面。

它接收的也是 2 个参数。第一个参数:func ,第二个参数:可迭代对象。

def fun(n):
    return n < 10

# 列表就是可迭代对象
li = [1, 2, 122, 331, 11, 22, 33, 4, 6, 7, 2, 88, 31]
res = filter(fun, li)

# map:将可迭代对象中的数据迭代出来,一个一个传到函数中去调用,将返回结果放到新的对象中。
res2=map(fun,li)
print(list(res2))

技术图片

它返回的结果全是TrueFalse

map()函数可以用来做:

1.把这些数据做统一的处理,比如算这些数据的阶乘,有一批数据要算阶乘,可以一起拿过去。

2.它会把数据当作个参数,放到函数里去调用。

3.然后把函数的返回值放到一个列表里面。

技术图片

它返回什么就放什么,改成返回 1000:

技术图片

改成n*2:

技术图片

map()将可迭代对象里面的元素迭代出来,每个元素当作一个参数,传到前面这个函数fun里面,然后把函数的返回值添加到新的列表里面。

技术图片

要统一处理一批数据的时候,就可以通过它来做。

三、zip()函数

1.什么是 zip()函数

zip()函数后面接收的是个可迭代对象,后面可接收多个可迭代对象。

技术图片

来看看 zip 的源码:

它的内部其实也是个类,那么它返回的就是个可迭代对象。

技术图片

准确得来说,它是个迭代器,迭代器也属于可迭代对象。

例如:

# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(res3)

在 Python2 的时候,filter()map()zip()函数返回出来的直接是列表。Python3 做了个性能的优化,返回的是个迭代器,可以节约内存。

技术图片

通过next()去取值,能获取出来内容的话,说明它就是个迭代器:

技术图片

直接一次性把它转换成列表,方便看结果:

# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(list(res3))

它是这样打包的:

使用zip()函数传入 2 个可迭代对象,把第一个可迭代对象的第一个元素和第二个可迭代对象的第一个元素拿出来打包成一个元组,后面以此类推。

技术图片

技术图片

为什么里面放的是元组?

元组省内存啊。

如果可迭代对象里面元素多少不一样(长短不一)怎么办?

# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33,44,55],[111,222,333],[111,222,333])
print(list(res3))

它会只会保留最短的。

技术图片

代码中最短的一组:这里只有 3 个元素。

那么这里的话,只会分成 3 组。就算第二组有 5 个元素,只会拿第一个、第二个、第三个。多余的数据清除掉了,不要了。

2.zip()可以快速创建字典

你看,和字典items()取值出来的数据是一样的:

技术图片

通过dict转换下,你看,它变成了一个字典:

# zip # 打包
res3 = zip([1, 2, 3], [11, 22, 33])
print(dict(list(res3)))

dict1={"key1":1,"key2":2,"key3":3}
print(list(dict1.items()))

技术图片

创建字典的时候,可通过这种方式快速创建字典。

把键放在一个列表里,把值放在一个列表里,通过zip()打包一下,通过dit()就能把它转换成一个字典。


公众号清菡软件测试首发,更多原创文章:清菡软件测试 112+原创文章,欢迎关注、交流,禁止第三方擅自转载。

本类排行

今日推荐

热门手游