Python basic series - iterators and built-in higher-order functions

Table of contents

1. Iterators

1. Basic concepts

2. How to define an iterator

3. If it is judged whether the object is an iterator

4. How to reset the iterator

5. How to call the iterator

Second, the generator

3. Higher-order functions

1. map function 

2. filter function

3. reduce function

4. sorted function


1. Iterators

1. Basic concepts

    Iteration : It is a repeated process, and each repetition is continued based on the previous result. Simple repetition is not iteration.

    Iterable object : refers to any object whose elements can be traversed using a for loop; common iterable objects include lists, tuples, strings, and dictionaries; all iterable objects have an __iter__() method.

setvar = {"a",1,"b",2}
for i in setvar:
	print(i)

res = dir(setvar)
print(res)

     Iterator : An iterator is an object that can traverse a collection from front to back; all iterable objects in Python have a __iter__() method, which returns an iterator object. This iterator object has a __next__() method that returns the next value in the sequence one by one. __next__() raises a StopIteration exception when there are no more values ​​to return

        The main problem solved by Python iterators is how to traverse all elements in a container (such as lists, tuples, dictionaries, etc.) without knowing the details of its internal implementation. By using iterators, we can access each element in the container one by one and stop the traversal when needed. This makes the code more concise and readable, and reduces the possibility of errors. In addition, iterators can also be used to perform lazy calculations in situations such as processing large data sets or infinite sequences, thereby improving program efficiency and performance.

setvar =  {"a",1,"b",2}
it = iter(setvar) 
print(it)
print(dir(it))

    Association : the relationship between iterable objects and iterators: never directly accessible => directly accessible. If it is an iterable object, it is not necessarily an iterator, and if it is an iterator, it must be an iterable object. You can use the dir() method to determine whether it is an iterator.

2. How to define an iterator

    Defined by iter() method

"""
	(1)iter(可迭代对象)
	(2)可迭代对象.__iter__()
"""
setvar =  {"a",1,"b",2}
it = iter(setvar) 
print(it) # iterator

3. If it is judged whether the object is an iterator

    Judging by the three-party package Iterator, Iterable

from collections import Iterator,Iterable
"""
    from 从哪里...  import 引入
    Iterator 迭代器类型 Iterable 可迭代对象
"""
# 判断setvar是否为可迭代对象
setvar = {"a","b","c"}
res = isinstance(setvar, Iterable)
print(res)

# 判断range是否为迭代器
it = iter(range(5))
res = isinstance(it,Iterator)
print(res)

4. How to reset the iterator

    Because iterators are irreversible, resetting requires a new call to

"""
next调用,单项不可逆,一条路走到黑
"""
it = iter(setvar)
res = next(it)
print(res)

5. How to call the iterator

    (1) next (iterator)
    (2) iterator. When the __next__()
    iterator is called by the next method, it is a one-way irreversible process

# 1.通过next获取迭代器中的数据
setvar = {"a", "b", "c"}
it = iter(setvar)
print(next(it))
print(next(it))
print(next(it))

# 2.通过for循环,遍历迭代器
print("<========>")
it = iter(range(6))
for i in it:
    print(i)
print("<========>")
# 3.for 和 next 配合调用迭代器
it = iter(range(100000))
for i in range(10): # 只调用前10个,0-9
    res = next(it)
    print(res)

print("<===>")
for i in range(10): # 没有重置,继续从10开始调用
    res = next(it)
    print(res)

Second, the generator

        The main problem solved by Python generators is how to generate data on demand when needed, without storing all the data in memory at once. By using generators, we can define a function or expression that yields each element in a sequence, and it is evaluated only when that element needs to be accessed. This makes the code more concise and readable, and reduces the possibility of errors. In addition, generators can also be used to perform lazy calculations in situations such as processing large data sets or infinite sequences, thereby improving program efficiency and performance.

# ### 生成器函数
"""
# yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走,而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
"""

# 1.生成器的好处是即使有1000个元素,调用时只需要先取5个再取3个,减少内存占用
def mygen():
    for i in range(1,1000):
        yield "号码%s" % (i)

# 初始化生成器函数 -> 生成器对象 -> 简称生成器
gen = mygen()

# for + next 调用生成器
for i in range(5):
	res = next(gen)
	print(res)

print("********************************")
for i in range(3):
	res = next(gen)
	print(res)


# 2.send 可以发送数据,发送给上一个yield
"""
### send
# next和send区别:
	next 只能取值
	send 不但能取值,还能发送值
# send注意点:
	第一个 send 不能给 yield 传值 默认只能写None
	最后一个yield 接受不到send的发送值
"""
def mygen():
	print("start")
	res = yield 111
	print(res)

	res = yield 222
	print(res)

	res = yield 333
	print(res)

	print("end")


# 初始化生成器函数 -> 返回生成器对象 -> 简称生成器
gen = mygen()

# 第一次调用
# 第一次只能默认发送None,因为第一次没有上一个yield
val = gen.send(None)
print(val)
print("***")
# 第二次调用
val = gen.send(444)
print(val)
print("***")
# 第三次调用
val = gen.send(555)
print(val)
print("***")


"""
无论是next 还是 send 都可以调用生成器里面的数据
send 不但可以调用,还可以给yield 发送值

第一次调用send , 只能发送None ,因为还没有遇到yield
代码从上到下执行, print("start") 遇到 res = yield 111
记录当前代码执行的状态87行,把111值返回,等待下一次调用
外面的val = 111  print(111)

# 第二次调用send ,把444发送给上一次保存的位置87行
yield 进行接收 res = 444  87行往下执行 print(444) 遇到 res = yield 222
记录当前代码执行的状态90行,把222值返回,等待下一次调用
外面的val = 222 print(222)

# 第三次调用send ,把555发送给上一次保存的位置90行
yield 进行接收 res = 555  90行往下执行 print(555) 遇到 res = yield 333
记录当前代码执行的状态93行,把333值返回,等待下一次调用
外面的val = 333 print(333)

# 第四次调用send , 把555发送给上一次保存的位置93行
yield 进行接收 res = 666  93行往下执行 print(666)  print("end")
没有任何yield 返回数据 , 出现StopIteration 
到此程序彻底结束.
"""


# 3.yield from : 将一个可迭代对象变成一个迭代器返回	

def mygen():
	lst = ["魏小林","陈宁波","朱胜"]
	yield from lst
gen = mygen()
print(next(gen))
print(next(gen))
print(next(gen))




# 4.案例: 用生成器来写一个斐波那契数列

"""
生成器应用在大数据的场景中,按照需求依次取值,
切记不要直接迭代生成器所有数据
一旦数据量较大,类似于死循环
"""
# 1 1 2 3 5 8 13 21 34 55 ..... 

def mygen(maxlength):
	a = 0
	b = 1
	
	i = 0
	while i < maxlength:
		# print(b)
		yield b
		# 当前值 = 上上个值 + 上一个值
		a,b = b,a+b
		i+=1

gen = mygen(50)
# 按照需求量进行取值
for i in range(30):
	print(next(gen))

3. Higher-order functions

    Higher-order functions: Those that can pass functions as parameters are higher-order functions, mainly including map, filter, reduce, and sort.

1. map function 

map(func,iterable)

功能:
    把iterable里面的数据一个一个拿出来,放到func函数中进行处理,把处理的结果扔到迭代器中,返回迭代器
参数:
    func 自定义函数 或者 内置函数
    iterable 可迭代对象 (容器类型数据 range 迭代器)
返回值:
    迭代器
备注:
    主要做批处理,把iterable里面的数据根据自己的规则进行处理,最终输出。
# 1.转换列表的字符串为数字
# ["1","2","3","4"] => [1,2,3,4]

lst = ["1","2","3","4"]
print(lst)
it = map(int,lst)
lst = list(it)
print(lst)

# 代码分析:map函数首先拿出列表当中的"1",扔到int函数当中处理,处理的结果扔到迭代器当中,依次遍历。然后通过list强转迭代器 ,返回一个列表。



# 2.处理列表的元素,整体变为二次方
# [1,2,3,4] => [1,4,9,16]

lst = [1,2,3,4]

# map方法一,自定义处理逻辑函数
def func(n):
	return n ** 2
it = map(func,lst)
# map方法二,利用匿名函数简化代码(推荐)
it = map( lambda n : n ** 2 , lst )

# 强转成列表,瞬间拿到所有数据
print(list(it))



# 3.根据字典的k或者v,取出对应的值
# dic = {97:"a",98:"b",99:"c"} 给你["a","b","c"] => 返回 [97,98,99]

lst = ["a","b","c"]
dic = {97:"a",98:"b",99:"c"}

def func(n):
    for k,v in dic.items():
        if n == v:
			return k
it = map(func,lst)
print(list(it))

2. filter function

filter(func,iterable)

功能:
	在自定义的函数中,过滤数据
	如果返回True  代表保留数据
	如果返回False 代表舍弃该数据
参数:
	func 自定义函数
	iterable 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
	迭代器
备注:
    这个函数f的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
# 提取列表所有的奇数
# 1.[1,2,3,4,5,6,7,8] => [1, 3, 5, 7]


lst = [1, 2, 3, 4, 5, 6, 7, 8]


def func(n):
    if n % 2 == 0:
        return False
    else:
        return True


it = filter(func, lst)

# 2.for
print("遍历输出所有元素")
it = filter(func, lst)
for i in it:
    print(i)

# 3.for + next
print("遍历输出前两个元素")
it = filter(func, lst)
for i in range(2):
	print(next(it))

# 4.list强转,瞬间得到所有数据
print("将所有结果强转为list")
it = filter(func, lst)
lst = list(it)
print(lst)

# 改写成lambda 表达式
print("lambda简化代码,结果不变")
lst = [1, 2, 3, 4, 5, 6, 7, 8]
it = filter(lambda n: True if n % 2 == 1 else False, lst)
print(list(it))

3. reduce function

reduce(func,iterable)

功能:
    一次性从iterable当中拿出2个值,扔到func函数中进行处理,把运算的结果在和iterable的第三个值继续扔到func中做运算
	 ... 以此类推 
	 最后返回计算的结果
参数:
	func 自定义函数
	iterable 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
	最后计算的结果
备注:
	类似聚合函数,利滚利
from functools import reduce

# 1.计算列表 [2, 4, 5, 7, 12] 中所有元素的乘积,然后再将结果与初始值 2 相乘
# 2*4*5*7*12 再*2

def prod(x, y):
    return x * y
print(reduce(prod, [2, 4, 5, 7, 12], 2))

# 解释:reduce() 函数会对序列中的每个元素依次执行 prod() 函数,并将前一次调用的结果作为下一次调用时的第一个参数传入。最终得到所有元素相乘的结果。


# 2.将列表转化为数字
# [5,4,8,8] => 5488

lst = [5,4,8,8]
def func(x,y):
	return x*10 + y
res = reduce(func,lst)
print(res, type(res))

"""
先从lst拿出前两个数据,5和4,扔到func当中进行运算 5 * 10 + 4 = 54
拿54 和 容器中第三个元素 8 , 扔到func当中进行运算 54 * 10 + 8 = 548 
拿548 和 容器中第四个元素 8 , 扔到func当中进行运算 548 * 10 + 8 = 5488
最后把5488 直接返回,程序结束.
"""

# 优化成lambda表达式写法
print( reduce(lambda x,y : x * 10 + y,lst) )

4. sorted function

sorted(iterable,reverse=False,key=函数)

功能:  
	对数据进行排序
参数: 
    iterable  : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
    reverse   : 是否反转 默认为False 代表正序, 改成True 为倒序
    key       : 指定函数 内置或自定义函数
返回值:
	返回排序后的数据
备注:
    可以对列表、元组等可迭代对象进行排序
# 1.对列表进行升序排列

lst = [3, 2, 4, 1]
print(sorted(lst))   # 输出:[1, 2, 3, 4]

# 2.对元组进行降序排列

tpl = (5, 7 ,6 ,8)
print(sorted(tpl, reverse=True))   # 输出:[8, 7 ,6 ,5]

# 3.按字符串长度对列表中的字符串进行升序排列

lst = ['apple', 'banana', 'pear', 'orange']
print(sorted(lst,key=len))   # 输出:['pear', 'apple', 'banana', 'orange']

# 4.对数组按照绝对值排序
lst = [3, -2, 4, 1, -10]
print(sorted(lst,key=abs))   # 输出:[1, -2, 3, 4, -10]

Guess you like

Origin blog.csdn.net/weixin_39855998/article/details/129382422