文章目录
1、迭代器、异步迭代器、枚举
range()
class range(stop)
class range(start, stop, step=1)
虽然被称为函数,但 range
实际上是一个不可变的序列类型,返回一个range
对象。
range
构造器的参数必须为整数(可以是内置的 int
或任何实现了 __index__()
特殊方法的对象)。
- 如果省略
step
参数,则默认为1
。 - 如果省略
start
参数,则默认为0
。 - 如果
step
为零
,则会引发ValueError
。 - 如果
step
为正值,确定range
r
内容的公式为r[i] = start + step*i
其中i >= 0
且r[i] < stop
。 - 如果
step
为负值,确定range
内容的公式仍然为r[i] = start + step*i
,但限制条件改为i >= 0
且r[i] > stop
。 - 如果
r[0]
不符合值的限制条件,则该range
对象为空。range
对象确实支持负索引,但是会将其解读为从正索引所确定的序列的末尾开始索引。 - 元素绝对值大于
sys.maxsize
的range
对象是被允许的,但某些特性 (例如len()
) 可能引发OverflowError
。
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(10, -1, -1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 不满足参数使用规则时返回空元素的range对象
>>> list(range(0, 10, -1))
[]
>>> list(range(0, 10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 我们常常拿range对象作为迭代次数限制或者作为序列类型的索引
>>> for i in range(10):
... print(i)
0
1
2
...省略
>>> nums = [1,2,3,4,5,6,7,8,9]
>>> for i in range(len(nums)):
... print(nums[i])
1
2
3
...省略
zip()
zip(*iterables, strict=False)
在多个迭代器上并行迭代,从每个迭代器返回一个数据项组成元组,返回值为一个zip对象。
- 默认情况下,
zip()
在最短
的迭代完成后停止。较长可迭代对象中的剩余项将被忽略,结果会裁切至最短可迭代对象的长度 - 如果只希望
zip()
用于可迭代对象等长的情况下。这时建议用strict=True
的选项。这将一个可迭代对象在其他几个之前被耗尽则会引发ValueError
zip()
与*
运算符相结合可以用来拆解一个列表
for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']):
... print(item)
...
(1, 'sugar')
(2, 'spice')
(3, 'everything nice')
# zip可以直接被解包赋值
>>> x1,x2,x3 = zip([1,2,3],[4,5,6])
>>> x1
(1, 4)
>>> x2
(2, 5)
>>> x3
(3, 6)
# *zip()拆解
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> x2, y2 = zip(*zip(x, y)) # 相当于zip((1,4),(2,5),(3,6)), x2与y2是元组类型
>>> x == list(x2) and y == list(y2)
True
# 用于生成字典
>>> dict(zip([1, 2, 3], ['sugar', 'spice', 'everything nice']))
{1: 'sugar', 2: 'spice', 3: 'everything nice'}
# 截断
>>> list(zip([1,2,3],[4,5,6,7,8,9]))
[(1, 4), (2, 5), (3, 6)]
enumerate()
enumerate(iterable, start=0)
返回一个枚举对象。iterable
必须是一个序列,或 iterator
,或其他支持迭代的对象。 enumerate()
返回的迭代器的 __next__()
方法返回一个元组,里面包含一个计数值(从 start
开始,默认为 0
)和通过迭代 iterable
获得的值。
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
>>> [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
# enumerate等价于
def enumerate(iterable, start=0):
n = start
for elem in iterable:
yield n, elem
n += 1
iter()
iter(object)
iter(object, sentinel)
返回一个iterator
对象。 根据是否存在第二个参数,对第一个参数的解读会有很大的不同。
如果没有第二个参数,object
必须是一个支持 iterable
协议 (有 __iter__()
方法) 的多项集对象,或者必须支持序列协议 (有 __getitem__()
方法并使用从0
开始的整数参数)。 如果它不支持这些协议,则会引发 TypeError
。
如果给出了第二个参数 sentinel
,则 object
必须是一个可调用对象
(callable
)。 在这种情况下创建的迭代器将针对每次调用其 __next__()
方法不带参数地调用 object
;如果返回的值等于 sentinel
,则会引发 StopIteration
,否则将返回该值。
如果使用iter(iterable)
迭代一个可迭代对象显得比较多余,因为iterable
本身就可以直接迭代,但是iter
有以下两点主要用途
- 控制配合
next()
控制迭代过程 - 使用
sentinel
进行打断
>>> iter_ele = iter([1,2,3])
>>> next(iter_ele)
1
>>> next(iter_ele)
2
>>> next(iter_ele)
3
>>> next(iter_ele)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> def get_input():
... return input("Enter something (or 'STOP' to end): ")
...
>>> # 创建迭代器,直到用户输入 'STOP'
... for user_input in iter(get_input, 'STOP'):
... print(f'You entered: {user_input}')
...
Enter something (or 'STOP' to end): 1
You entered: 1
Enter something (or 'STOP' to end): 2
You entered: 2
Enter something (or 'STOP' to end): 3
You entered: 3
Enter something (or 'STOP' to end): 4
You entered: 4
Enter something (or 'STOP' to end): STOP
# 在一些复杂的场景加也可以自定义迭代过程
>>> def get_next_value():
... values = [3, 2, 1, 0, -1, -2]
... for value in values:
... yield value
>>> # 创建生成器
... value_generator = get_next_value()
>>>
>>> # 定义一个可调用对象来获取下一个值
... def next_value():
... return next(value_generator)
>>> # 使用可调用对象和哨兵值创建迭代器
... my_iter = iter(next_value, 0)
>>>
>>> # 使用迭代器遍历
... for item in my_iter:
... print(item)
...
3
2
1
aiter()
aiter(async_iterable)
返回 asynchronous iterable
的 asynchronous iterator
。相当于调用 x.__aiter__()
。
在python 3.10.才开始添加
>>> import asyncio
# 使用next()迭代
>>> async def async_generator():
... yield 1
... await asyncio.sleep(1) # 模拟异步操作
... yield 2
... await asyncio.sleep(1) # 模拟异步操作
... yield 3
...
>>> async def main():
... async_iterable = async_generator()
... async_iterator = aiter(async_iterable)
... while True:
... try:
... value = await anext(async_iterator)
... print(value)
... except StopAsyncIteration:
... break
...
>>> asyncio.run(main())
1
2
3
# 使用for in 迭代
>>> async def async_gen():
... for i in range(3):
... await asyncio.sleep(1)
... yield i
...
>>> async def main():
... async for item in aiter(async_gen()):
... print(item)
...
>>> asyncio.run(main())
0
1
2
next()
next(iterator)
next(iterator, default)
通过调用 iterator
的 __next__()
方法获取下一个元素。如果迭代器耗尽,则返回给定的 default
,如果没有默认值则触发 StopIteration
。
>>> # 使用 next() 函数遍历迭代器
... my_iter = iter([1, 2, 3])
... while True:
... try:
... # 获取下一个元素
... element = next(my_iter)
... print(element)
... except StopIteration:
... # 没有更多元素,退出循环
... print("Iteration complete.")
... break
1
2
3
Iteration complete.
# 使用 next() 函数手动控制迭代
>>> my_iter = iter([1, 2, 3, 4, 5])
>>> next(my_iter)
1
>>> next(my_iter)
2
>>> next(my_iter)
3
# 使用 `next()` 函数获取下一个元素,并设置默认值
>>> my_iter = iter([1, 2, 3])
>>> print(next(my_iter, 0))
1
>>> print(next(my_iter, 0))
2
>>> print(next(my_iter, 0))
3
>>> print(next(my_iter, 0))
0
anext()
awaitable anext(async_iterator)
awaitable anext(async_iterator, default)
当进入 await
状态时,从给定 asynchronous iterator
返回下一数据项,迭代完毕则返回 default
。
这是内置函数 next()
的异步版本,类似于:
调用 async_iterator
的 __anext__()
方法,返回一个 awaitable
。等待返回迭代器的下一个值。若有给出 default
,则在迭代完毕后会返回给出的值,否则会触发 StopAsyncIteration
。
在python 3.10.才开始添加
>>> import asyncio
>>> async def async_gen():
... for i in range(3):
... await asyncio.sleep(1)
... yield i
>>> async def main():
... agen = async_gen()
... print(await anext(agen, 'default'))
... print(await anext(agen, 'default'))
... print(await anext(agen, 'default'))
... print(await anext(agen, 'default'))
... print(await anext(agen, 'default'))
>>> asyncio.run(main())
0
1
2
default
default
2具有固定功能的简化迭代
all()
all(iterable)
如果 iterable
的所有元素均为真值(或可迭代对象为空)则返回 True
。等价于:
def all(iterable):
for element in iterable:
if not element:
return False
return True
>>> all([1,2,3])
True
>>> all([1,2,3,0])
False
>>> all([1,2,3,""])
False
>>> all(i > 3 for i in [1,2,3,4])
False
>>> all(i.isalpha() for i in "ALPHA1")
False
any()
如果 iterable
的任一元素为真值则返回 True
。 如果可迭代对象为空,返回 False
。 等价于:
def any(iterable):
for element in iterable:
if element:
return True
return False
>>> any([0,"",{},set(),None,0.0,False])
False
>>> any([0,"",{},set(),None,0.0,False,1])
True
filter()
filter(function, iterable)
使用 iterable
中 function
返回真值的元素构造一个迭代器。 iterable
可以是一个序列,一个支持迭代的容器或者一个迭代器。 如果 function
为 None
,则会使用标识号函数,也就是说,iterable
中所有具有假值的元素都将被移除。
请注意, filter(function, iterable)
相当于一个生成器表达式,当 function
不是 None
的时候为 (item for item in iterable if function(item))
;function
是 None
的时候为 (item for item in iterable if item)
。
# 过滤掉奇数
>>> filter(lambda x: x % 2 == 0, range(10))
<filter object at 0x000001B7AD2FB128>
>>> list(filter(lambda x: x % 2 == 0, range(10)))
[0, 2, 4, 6, 8]
# 过滤空字符串
>>> list(filter(lambda x: x, ["hello", "", "world", " ", "python", ""]))
['hello', 'world', ' ', 'python']
# 过滤空字符串和空格字符串
>>> list(filter(lambda x: x.strip(), ["hello", "", "world", " ", "python", ""]))
['hello', 'world', 'python']
map()
map(function, iterable, *iterables)
返回一个将 function
应用于 iterable
的每一项,并产生其结果的迭代器。 如果传入了额外的 iterables
参数,则 function
必须接受相同个数的参数并被用于到从所有可迭代对象中并行获取的项。 当有多个可迭代对象时,当最短的可迭代对象耗尽则整个迭代将会停止。
>>> map(lambda x: x**2, [1,2,3,4])
<map object at 0x000001B7AF063320>
>>> list(map(lambda x: x**2, [1,2,3,4]))
[1, 4, 9, 16]
>>> list(map(lambda x: int(x), [1,2,'3']))
[1, 2, 3]
>>> list(map(sorted, [[3, 1, 2], [9, 7, 8], [6, 5, 4]]))
[[1, 2, 3], [7, 8, 9], [4, 5, 6]]
>>> list(map(max, [[3, 1, 2], [9, 7, 8], [6, 5, 4]]))
[3, 9, 6]
slice()
class slice(stop)
class slice(start, stop, step=None)
返回一个表示由 range(start, stop, step)
指定的索引集的 slice
对象。 start
和 step
参数默认为 None
。
>>> [1, 2, 3, 4, 5][slice(1,4)]
[2, 3, 4]
>>> [1, 2, 3, 4, 5][slice(1,4,2)]
[2, 4]
>>> "Hello, World!"[slice(1,6,2)]
'el,'
>>> "Hello, World!"[1:6:2]
'el,'
>>> slice(1, None, 2)
slice(1, None, 2)
>>> [1,2,3,4,5][slice(1, None, 2)]
[2, 4]
reversed()
返回一个反向的新的 iterator
。 seq
必须是一个具有 __reversed__()
方法或是支持序列协议(具有 __len__()
方法和从 0
开始的整数参数的 __getitem__()
方法)的对象。
>>> reversed([1,2,3,4,5])
<list_reverseiterator object at 0x000001B79D72ACC0>
>>> list(reversed([1,2,3,4,5]))
[5, 4, 3, 2, 1]
# 自定义一个调换奇偶顺序
>>> class MyCustomSequence:
... def __init__(self, data):
... self.data = data
... def __len__(self):
... return len(self.data)
... def __getitem__(self, index):
... return self.data[index]
... def __reversed__(self):
... return self.data[0::2] + self.data[1::2]
>>> data = MyCustomSequence([1,2,3,4,5])
>>> reversed(data)
[1, 3, 5, 2, 4]
sorted()
sorted(iterable, /, *, key=None, reverse=False)
根据 iterable 中的项返回一个新的已排序列表。
- 具有两个可选参数,它们都必须指定为关键字参数。
>>> sorted([4,3,5,6])
[3, 4, 5, 6]
key
指定带有单个参数的函数,用于从iterable
的每个元素中提取用于比较的键 (例如key=str.lower
)。 默认值为None
(直接比较元素)。
>>> sorted(['banana', 'cherry', 'apple'], key=len)
['apple', 'banana', 'cherry']
reverse
为一个布尔值。 如果设为True
,则每个列表元素将按反向顺序比较进行排序。
>>> sorted(['apple', 'banana', 'cherry'], key=len, reverse=True)
['banana', 'cherry', 'apple']
- 使用
functools.cmp_to_key()
可将老式的cmp
函数转换为key
函数。cmp
的返回值必须是0,1,-1
,分别表示相等、大于、小于
>>> from functools import cmp_to_key
>>> def compare(a, b):
... return (a > b) - (a < b) # 0,1,-1
>>> sorted(['apple', 'banana', 'cherry'], key=cmp_to_key(compare))
['apple', 'banana', 'cherry']
- 内置的
sorted()
确保是稳定的。 如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 — 这有利于进行多重排序(例如先按部门、再按薪级排序)。
>>> sorted([('apple', 2), ('banana', 1), ('cherry', 2)], key=lambda x: x[1])
[('banana', 1), ('apple', 2), ('cherry', 2)]
- 排序算法只使用
<
在项目之间比较。 虽然定义一个__lt__()
方法就足以进行排序,但 PEP 8 建议实现所有六个 富比较 。 这将有助于避免在与其他排序工具(如max()
)使用相同的数据时出现错误,这些工具依赖于不同的底层方法。实现所有六个比较也有助于避免混合类型比较的混乱,因为混合类型比较可以调用反射到__gt__()
的方法
>>> class MyClass:
... def __init__(self, value):
... self.value = value
...
... def __lt__(self, other):
... return self.value < other.value
...
... def __eq__(self, other):
... return self.value == other.value
>>> sorted([MyClass(3), MyClass(1), MyClass(2)])
[<__main__.MyClass object at 0x000001B79D730828>, <__main__.MyClass object at 0x000001B79D7309B0>, <__main__.MyClass object at 0x000001B79D730978>]
>>> [i.value for i in sorted([MyClass(3), MyClass(1), MyClass(2)])]
[1, 2, 3]
字典排序
# 按键排序
>>> dict(sorted(my_dict.items()))
{'apple': 2, 'banana': 3, 'cherry': 1}
# 按值排序
>>> dict(sorted(my_dict.items(), key = lambda x:x[1]))
{'cherry': 1, 'apple': 2, 'banana': 3}
sum()
sum(iterable, /, start=0)
从 start
开始(这里的start是说以start
为初始值,然后一直从iterable[0]+...+iterable[len(iterable)-1]
,请注意并不是从iterable[start]+...+iterable[len(iterable)-1]
),自左向右对 iterable
的项求和并返回总计值。 iterable
的项通常为数字,而 start
值则不允许为字符串。
在 3.8 版本发生变更:
start
形参可用关键字参数形式来指定。
在 3.12 版本发生变更: 对浮点数求和的算法已更改为一种在大多数构建中提供更高精度的算法
>>> sum([1,2,3])
6
>>> sum([1,2,3], 1)
7
# 3.8变笨前并没有start形参
>>> sum([1,2,3], start = 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() takes no keyword arguments
# 3.8版本之后
>>> sum([1,2,3], start=1)
7
max()
max(iterable, *, key=None)
max(iterable, *, default, key=None)
max(arg1, arg2, *args, key=None)
返回可迭代对象中最大的元素,或者返回两个及以上实参中最大的。
如果只提供了一个位置参数,它必须是非空 iterable
,返回可迭代对象中最大的元素;如果提供了两个及以上的位置参数,则返回最大的位置参数。
有两个可选只能用关键字的实参。key
实参指定排序函数用的参数,如传给 list.sort()
的。default
实参是当可迭代对象为空时返回的值。如果可迭代对象为空,并且没有给 default
,则会触发 ValueError
。
如果有多个最大元素,则此函数将返回第一个找到的。这和其他稳定排序工具如 sorted(iterable, key=keyfunc, reverse=True)[0]
和 heapq.nlargest(1, iterable, key=keyfunc)
保持一致。
在 3.4 版本发生变更: 增加了 default 仅限关键字形参。
在 3.8 版本发生变更: key 可以为 None。
>>> max([6,3,2,5])
6
>>> max(6,3,2,5)
6
# 根据元组索引1位置最大值
>>> max((1,2),(2,5),(5,1), key=lambda x:x[1])
(2, 5)
# 直接对字典求max得到键的max
>>> max({"a":3,"c":4,"b":1})
'c'
# 得到key最大的key-val
>>> max({"a":3,"c":4,"b":1}.items())
('c', 4)
# 得到val最大的key-val
>>> max({"a":3,"c":4,"b":1}.items(), key=lambda x:x[1])
('c', 4)
# 空sequence会使用默认值
>>> max([],default=0)
0
# 空sequence没有默认值时会报错
>>> max([])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence
min()
min(iterable, *, key=None)
min(iterable, *, default, key=None)
min(arg1, arg2, *args, key=None)
返回可迭代对象中最小的元素,或者返回两个及以上实参中最小的。
min()
与max()
功能相反,使用形式相同
在 3.4 版本发生变更: 增加了 default 仅限关键字形参。
在 3.8 版本发生变更: key 可以为 None。
>>> min([6,3,2,5])
2
>>> min(6,3,2,5)
2
# 根据元组索引1位置最小值
>>> min((1,2),(2,5),(5,1), key=lambda x:x[1])
(5, 1)
# 直接对字典求min得到键的min
>>> min({"a":3,"c":4,"b":1})
'a'
# 得到key最小的key-val
>>> min({"a":3,"c":4,"b":1}.items())
('a', 3)
# 得到val最小的key-val
>>> min({"a":3,"c":4,"b":1}.items(), key=lambda x:x[1])
('b', 1)
# 空sequence会使用默认值
>>> min([],default=0)
0
# 空sequence没有默认值时会报错
>>> min([])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence
len()
len(s)
返回对象的长度(元素个数)。实参可以是序列(如 string
、bytes
、tuple
、list
或 range
等)或集合(如 dictionary
、set
或 frozen set
等)。len
对于大于 sys.maxsize
的长度如 range(2 ** 100)
会引发 OverflowError
。
当s
不是基本类型时,会将len()
转交给s.__len__()
>>> len([1,2,3,4])
4
>>> class MyCustomClass:
... def __init__(self, data):
... self.data = data
... def __len__(self):
... return len(self.data)
...
>>> my_object = MyCustomClass([1, 2, 3, 4, 5])
>>> len(my_object)
5