python (第八章)补充-可迭代对象(补充高阶函数,以及常用的高阶函数)

22 篇文章 0 订阅
15 篇文章 0 订阅

可迭代对象

我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象。

>>> isinstance([], Iterable)
True
>>> isinstance(range(1),Iterable)
True

range() 函数可创建一个整数列表,一般用在 for 循环中。

迭代器

什么是迭代器

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()函数。

对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是python内置函数。 iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。

迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。

在这里插入图片描述

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

什么是生成器

在这里插入图片描述
在这里插入图片描述

生成器的作用

首先,生成器的好处是延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

除了延迟计算(减少内存使用),生成器还能有效调高代码可读性。

生成器的注意事项

生成器的唯一注意事项是:生成器只能遍历一次。

总结:

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的。

高阶函数

什么是高阶函数?

高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

实例1(参数为函数):

def bar():
    print('in the bar')
def foo(func):
    func()
    print('in the foo...')
foo(bar)
"""
in the bar
in the foo...
"""

实例2(返回值为函数)

def bar():
    print("in the bar...")
def foo(func):
    print("in the foo")
    return func
res = foo(bar)
res()

"""
in the foo
in the bar...
"""

map()函数

map()函数接收两个参数,一个是函数,一个是Iterable。

例子1:

def f(x):
	return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(r))
# [1, 4, 9, 16, 25, 36, 49, 64, 81]

例子2:

print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
# ['1', '2', '3', '4', '5', '6', '7', '8', '9']

例子3:加入生成器表达式

def f(x):
	return x * x
r = map(f, (x for x in range(1, 10)))
print(list(r))
# [1, 4, 9, 16, 25, 36, 49, 64, 81]

filter()函数

filter函数也是接收一个函数和一个序列的高阶函数,其主要功能是过滤。其返回值是迭代器对象。

names = ["Alex", "amanda", "xiaowu"]
#filter函数机制
def filter_test(func, iter):
    names_1 = []
    for i in iter:
        if func(i): #传入的func函数其结果必须为bool值,才有意义
            names_1.append(i)
    return names_1
#filter_test函数
print(filter_test(lambda x: x.islower(), names))
#filter函数
print(list(filter(lambda x: x.islower(), names)))

reduce()函数

reduce:把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

例子1:

from functools import reduce
def add(x, y):
	 return x + y
print(reduce(add, [1, 3, 5, 7, 9]))
#25

例子2(计算阶乘):

from functools import reduce
def fact(n):
    return reduce(lambda a, b: a*b, range(1, n+1))
print(5)
#120

附例子2:
这里使用到了一个包operator

from functools import reduce
from operator import mul
def fac1(n):
    return reduce(mul, range(1, n+1))

点进去,我们发现这个包里有很多的方法;
在这里插入图片描述

例子3(字符串转化为数字):

from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
    def fn(x, y):
        return x * 10 + y
    def char2num(s):
        return DIGITS[s]
    return reduce(fn, map(char2num, s))
print(str2int('123'))
# 123

例子4(使用lambda函数修改一下例子3):

from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def char2num(s):
    return DIGITS[s]
def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))
print(str2int('123'))

例子5(把字符串’123.456’转换成浮点数123.456):

from functools import reduce
def str2float(s):
    def fn(x,y):
            return x*10+y
    n=s.index('.')
    s1=list(map(int,[x for x in s[:n]]))
    s2=list(map(int,[x for x in s[n+1:]]))
    return reduce(fn,s1)+reduce(fn,s2)/10**len(s2)

参考

(1)https://www.zhihu.com/question/20829330(如何更好地理解Python迭代器和生成器?)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值