lblbk.github.io

Python常用函数

记录一些python常用的函数api,以及日常使用小技巧

迭代器、生成器

可迭代对象

可以利用 for 循环的对象,都叫可迭代对象,实现有两种方式

# 对象内部实现 __iter__()方法
class myList:
    mylist = [0,1,2]

    # 返回迭代器类的实例
    def __iter__(self):
        return iter(self.mylist)

# 得到可迭代对象
my_list = myList()
print(isinstance(my_list, Iterable)) # True
for i in my_list:
    print(i)

    
# 实现 __getitem()__方法
class myList:
    mylist = [0,1,2]

    def __getitem__(self, item):
        return self.mylist[item]

# 得到一个可迭代对象
my_list = myList()
print(isinstance(my_list, Iterable)) # False isinstance 这种方法就是检查对象是否有 __iter__ 方法
for i in my_list:
    print(i)
迭代器

对可迭代对象使用 iter() 函数后,返回一个迭代器对象,可使用 next() 去元素,全部获取完毕,会抛出 StopIteration 提示无元素可取

迭代器实现在可迭代对象基础上实现 __next__() 函数,

>>> list = [0, 1, 2, 3]
>>> gen = iter(list)
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
3
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]
        
>>> rev = iter(Reverse('spam'))
>>> for char in rev:
...     print(char)
...
m
a
p
s

生成器

一个可以像迭代器那样使用for循环来获取元素的函数, 生成器的出现(Python 2.2 +),实现了延时计算,从而缓解了在大量数据下内存消耗过猛的问题, 会自动创建 __iter__()__next__()方法

# 列表推导式正常使用
>>> l1 = [i for i in rage(5)]
>>> l1
[0, 1, 2, 3, 4]

# generator 
>>> gen = (i for i in range(5))
>>> gen
<generator object <genexpr> at 0x000002835B6DC648>

# yield()
# 当一个函数运行到 yield 后,函数的运行会暂停,并且会把 yield 后的值返回出去。
# 若 yield 没有接任何值,则返回 None
# yield 虽然返回了,但是函数并没有结束
>>> def gen_func(top=5):
...     index=0
...     while index < top:
...             print(index)
...             index += 1
...             yield index
...     raise StopIteration
...
>>> gen = gen_func()
>>> gen
<generator object gen_func at 0x000002835B8E2848>
# next()
>>> gen = (i for i in range(3))
>>> gen
<generator object gen_func at 0x000002835B8E2848>
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

# for
>>> gen = (x for x in range(3))
>>> for i in gen:
...     print(i)
...
0
1
2
# next()

# generator.send(None) 相当于 next(gen)
def generator_factory(top=5):
     index = 0
     while index < top:
         index = index + 1
         yield index
     raise StopIteration

>>> gen = generator_factory()
>>> gen.send(None)
1
>>> gen.send(None)
2
# GEN_CREATED # 生成器已创建,还未被激活
# GEN_RUNNING # 解释器正在执行(只有在多线程应用中才能看到这个状态)
# GEN_SUSPENDED # 在 yield 表达式处暂停
# GEN_CLOSED # 生成器执行结束
# inspect包可检测
from inspect import getgeneratorstate

zip() *zip() zip(*zipped)

创建一个聚合了来自每个可迭代对象中的元素的迭代器

zip()* 运算符相结合可以用来拆解一个列表, 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同

# zip() *zip()
>>> a = ['a', 'b']
>>> b = [0, 1, 2]
>>> z = zip(a, b)
>>> z
<zip object at 0x00000133FC0F5208>
>>> list(z)
[('a', 0), ('b', 1)]
>>> x, y = zip(*zip(a, b))
>>> x
('a', 'b')
>>> y
(0, 1)
# zip(*zipped)  *zipped:可以list, 元组,也可以是zip()函数返回的对象
>>> nums = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']]
>>> iters = zip(*nums)
>>> iters
<zip object at 0x000002583AF7A688>
>>> list(iters)
[('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]

map() reduce() sorted()

# reduce源码 function是将要进行的操作
def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value

# reduce(function, iterable[, initializer])
# example
from functools import reduce 
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
reduce(lambda x, y: x*y, [1, 2, 3, 4, 5])

# output
15
120
# map(function_to_apply, list_of_inputs)  返回迭代器
list(map(lambda x: x**2, [1, 2, 3]))
# output [1, 4, 9]

偏函数 filter()

# functools.partial(func, *args, **keywords)
from functools import partial

int2 = partial(int, base=2)
res = int2('10000')
print(res) # 16

星号 * 用法 (一直困扰我)

乘法运算符 基本用法

1 * 1

收集列表中多余的值

a, b, *c = [1, 2, 3, 4]
# a是1,b是2,c是[3, 4] 列表

函数 用于收集参数或者分配参数

字典

for k, v in dict.items():
    print(k, v)
dict.get(key, default=None)

key – 字典中要查找的键。

default – 如果指定键的值不存在时,返回该默认值

位运算符

Python 的位运算符共 6 个

运算符 描述
& 按位“与”运算符:参与运算的两个值,如果两个相应位都为 1,则结果为 1,否则为 0
| 按位“或”运算符:只要对应的两个二进制位有一个为 1 时,结果就为 1
^ 按位“异或”运算符:当两对应的二进制位相异时,结果为 1
~ 按位“取反”运算符:对数据的每个二进制位取反,即把 1 变为 0,把 0 变为 1
« “左移动”运算符:运算数的各二进制位全部左移若干位,由“«”右边的数指定移动的位数,高位丢弃, 低位补 0
» “右移动”运算符:运算数的各二进制位全部右移若干位,由“»”右边的数指定移动的位数
>>> a=55  #a=0011 0111
>>> b=11  #b=0000 1011
>>> print(a&b)
3
>>> print(a|b)
63
>>> print(a^b)
60
>>> print(~a)
-56
>>> print(a<<3)
440
>>> print(a>>3)
6

[Reference]

iter_generator

3.5 【基础】迭代器

3.6 【基础】生成器)

Python中的*(星号)和**(双星号)完全详解