Python函数之常见内置函数及迭代器和生成器

常见内置函数

  • abs() 求绝对值

    >>> abs(-99)
    99
    >>> abs(100.10)
    100.1
    
  • all() 与 any() 判断容器类型中的所有数据值对应的布尔值是否为True

    # all()  所有的数据值都为True的情况下,结果才是True
    >>> all([1, 2, 3, 4, 5, 0])
    False
    >>> all([1, 2, 3, 4, 5])
    True
    
    # any()  所有的数据值只要有一个为True 结果就是True
    >>> any([1, 2, 3, 4, 5, 0])
    True
    >>> any([1, 2, 3, 4, 5])
    True
    
  • bin() oct() hex() int() 进制转换

    >>> bin(10)  # 返回一个整数 int 或者长整数 long int 的二进制表示的字符串
    '0b1010'
    >>> oct(10)  # 将一个整数(十进制)转换为一个八进制字符串,八进制以 0o 作为前缀表示
    '0o12'
    >>> hex(10)  # 将一个整数(十进制)转换为一个十六进制字符串,十六进制以 0x 作为前缀表示
    '0xa'
    
    # 将一个字符串或数字转换为整型(十进制)
    >>> int(0b1010)
    10
    >>> int(0o12)
    10
    >>> int(0xa)
    10
    
  • bytes() 类型转换

    # 编码(人类的字符>>>计算机的字符)
    >>> res = '啊吧啊吧'.encode('utf8')
    >>> res
    b'\xe5\x95\x8a\xe5\x90\xa7\xe5\x95\x8a\xe5\x90\xa7'
    # 解码(计算机的字符>>>人类的字符)
    >>> res1 = res.decode('utf8')
    >>> res1
    '啊吧啊吧'
    
    # bytes() 返回一个新的 bytes 对象
    >>> res = bytes('啊吧啊吧','utf8')
    >>> res
    b'\xe5\x95\x8a\xe5\x90\xa7\xe5\x95\x8a\xe5\x90\xa7'
    >>> type(res)
    <class 'bytes'>
    >>> res1 = str(res,'utf8')
    >>> res1
    '啊吧啊吧'
    
    >>>a = bytes([1,2,3,4])
    >>> a
    b'\x01\x02\x03\x04'
    >>> type(a)
    <class 'bytes'>
    
  • callable() 用于检查一个对象是否是可调用的

    >>> callable(0)
    False
    
    >>> name = 'kwan'
    >>> callable(name)
    False
    
    >>> def add(a, b):
    ...     return a + b
    ... 
    >>> callable(add)  # 函数返回 True
    True
    
  • chr() ord() 依据ASCII码表实现字符与数字的转换

    >>> chr(65)   # A~Z  65~90
    'A'
    >>> ord('A')
    65
    
    >>> chr(97)   # a~z  97~122 
    'a'
    >>> ord('a')
    97
    
  • dir() 获取对象内部可以通过句点符获取的数据

    # dir() 不带参数时,返回当前范围内的变量、方法和定义的类型列表
    >>>dir()   #  获得当前模块的属性列表
    ['__builtins__', '__doc__', '__name__', '__package__', 'arr', 'myslice']
    
    >>> dir([ ])    # 查看列表的方法
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    
    # dir() 带参数时,返回参数的属性、方法列表
    >>> dir(list)  # 查看列表的方法
    ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    
  • divmod() 获取除法之后的整数和余数

    # divmod() 接收两个数字类型(非复数)参数,返回一个包含商和余数的元组(a // b, a % b)
    >>> divmod(7, 2)
    (3, 1)
    >>> divmod(8, 2)
    (4, 0)
    >>> divmod(8, -2)
    (-4, 0)
    >>> divmod(3, 1.3)
    (2.0, 0.3999999999999999)
    
    
    """
    手上有很多数据 每页展示10条 需要多少页
        通过代码自动计算
    
    总数据         每页展示            需要多少页
     100            10                  10
     99             10                  10
     101            10                  11
     898            10                  ???
    """
    >>> real_num, more = divmod(898, 10)
    >>> if more:
    ...     real_num += 1
    ...
    >>> print('总页数:%s' % real_num)
    总页数:90
    
    

迭代器

迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动,是访问集合元素的一种方式,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代

# 不属于迭代
while True:
    msg = input('请输入: ').strip()
    print(msg)
    
    
# 属于迭代
n = 0
while n < 10:
    print(n)
    n += 1
    
''' 不仅满足重复,而且以每次重新赋值后的 n 值作为下一次循环中新的值,反复迭代 '''

可迭代对象

  1. 内置有 __iter__ 方法的对象都是可迭代对象,即字符串、列表、元组、字典、集合、打开的文件都是可迭代对象
  2. 可迭代对象能够支持 for 循环取值
# 判断可迭代对象,通过句点符直接能够点出来 __iter__ 

# 字符串
str.__iter__()
# 列表
list.__iter__()
# 字典
{'name': 'kwan'}.__iter__()
# 集合
{1, 2, 3, 4, 5}.__iter__()
# 元组
(1, 2, 3, 4, 5).__iter__()
# 文件
f = open(r'userinfo.txt', 'r', encoding='utf8').__iter__()

迭代器对象

索引的方式进行迭代取值,仅适用于序列类型:字符串,列表,元组。

对于没有索引的字典、集合等非序列类型,迭代器提供了不依赖索引来进行迭代取值的方式。

  • 调用 obj.__iter__() 方法返回的结果就是一个迭代器对象(Iterator)
  • 迭代器对象是内置有 __iter____next__ 方法的对象
  • 打开的文件本身就是一个迭代器对象
  • 执行迭代器对象 .__iter__() 方法得到的仍然是迭代器本身,而执行迭代器 .__next__() 方法就会计算出迭代器中的下一个值。
# 字符串
>>> res = 'kwan'.__iter__()   # 返回一个迭代器对象 赋值给res
>>> res.__next__()
'k'
>>> res.__next__()
'w'
>>> res.__next__()
'a'
>>> res.__next__()
'n'
>>> res.__next__()  # 没有了就直接报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

# 字典
>>> dict1 = {'name':'kwan','pwd':123}
>>> res = dict1.__iter__()  # 返回一个迭代器对象 赋值给res
>>> res.__next__()
'name'
>>> res.__next__()
'pwd'
>>> res.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


# 需求:不使用for循环 依次打印出列表中所有的数据值
>>> l1 = [11, 22, 33, 44, 55, 66]
>>> # 1.先将列表变成迭代器对象
>>> res = l1.__iter__()
>>> # 2.定义一个计数器
>>> count = 0
>>> # 3.编写while循环
>>> while count < len(l1):
...     print(res.__next__())
...     count += 1
...
11
22
33
44
55
66

迭代器的反复使用

>>> l1 = [11, 22, 33, 44]
>>> l1.__iter__().__next__()
11
>>> l1.__iter__().__next__()
11
>>> l1.__iter__().__next__()
11
>>> l1.__iter__().__next__()
11
''' l1.__iter__() 每次都是产生了一个新的迭代器对象 '''


>>> res = l1.__iter__()  # res为迭代器对象
>>> res.__iter__().__next__()
11
>>> res.__iter__().__next__()
22
>>> res.__iter__().__next__()
33
>>> res.__iter__().__next__()
44
''' 迭代器对象 .__iter__() 方法得到的仍然是迭代器本身,则每次使用的都是一个迭代器对象 '''

双下方法的简写

l.__iter__() # 可以简写iter(l)

res.__next__()  # 可以简写next(res)

for循环内部原理

for 循环又称为迭代循环,in 后可以跟任意可迭代对象

  1. for 会自动将 in 后面的数据调用__iter__()变成迭代器对象
  2. 之后每次循环调用__next__()取值
  3. 最后没有值__next__()会报错,for能够自动处理该错误,让循环正常结束
# 语法结构
for 变量名 in 可迭代对象:
	for循环体代码

生成器

  • 在 Python 中,使用了 yield 的函数被称为生成器(generator)。
  • 生成器是一个返回迭代器的函数,只能用于迭代操作。
  • 生成器内置有__iter____next__方法,所以生成器本身就是一个迭代器。

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

# 若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象 
>>> def my_range(start, stop, step=1):
...     print('start...')
...     while start < stop:
...         yield start
...         start += step
...     print('end...')
...
>>> res = my_range(0, 3)
>>> res
<generator object my_range at 0x00000268F0FA6580>

# 
>>> res.__iter__
<method-wrapper '__iter__' of generator object at 0x00000268F0FA6580>
>>> res.__next__
<method-wrapper '__next__' of generator object at 0x00000268F0FA6580>

>>> next(res) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
>>> next(res) # 再次调用next(res),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
>>> next(res) # 周而复始...
2
>>> next(res) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

生成器对象代码实现

  • 当函数体代码中有yield关键字,那么函数名第一次加括号调用不会执行函数体代码,而是由普通的函数变成了迭代器对象(生成器)返回值
>>> def index():
...     print('啊吧啊吧')
...     yield
...
>>> print(index)
<function index at 0x00000268F1214310>
>>> res = index()
>>> print(res)
<generator object index at 0x00000268F0FA6740>
  • yield可以在函数体代码中出现多次,每次调用__ next__方法都会从上往下执行直到遇到yield代码停留在此处
>>> def index():
...     print('啊吧啊吧')
...     yield 1
...     print('嘀嘀嘀')
...     yield 2
...     print('嘿嘿嘿')
...     yield 3
...
>>> index
<function index at 0x00000268F0E5E040>
>>> res = index()
>>> print(res)
<generator object index at 0x00000268F0FA6580>
>>> res.__next__()
啊吧啊吧
1
>>> res.__next__()
嘀嘀嘀
2
>>> res.__next__()
嘿嘿嘿
3
  • yield后面如果有数据值,则会像return一样返回回去,如果有多个数据值逗号隔开,那么也会自动组织成元组返回
>>> def index():
...     print('啊吧啊吧')
...     yield 1, 2, 3
...     print('嘀嘀嘀')
...     yield 2
...     print('嘿嘿嘿')
...     yield 3
...
>>> index
<function index at 0x00000268F1214310>
>>> res = index()
>>> res
<generator object index at 0x00000268F0FA6740>
>>>
>>> res.__next__()
啊吧啊吧
(1, 2, 3)
>>> res.__next__()
嘀嘀嘀
2
>>> res.__next__()
嘿嘿嘿
3

生成器练习题

# 编写生成器,实现range方法的功能
# 1.先以两个参数的功能编写
def my_range(start_num, end_num):
    while start_num < end_num:
        yield start_num
        start_num += 1

for i in my_range(1, 10):
    print(i)

# 2.再考虑一个参数的情况
def my_range(start_num, end_num=None):
    if not end_num:
        end_num = start_num
        start_num = 0
    while start_num < end_num:
        yield start_num
        start_num += 1
for i in my_range(100):
    print(i)

# 3.最后考虑三个参数的情况
def my_range(start_num, end_num=None, step=1):
    if step < 1:
        step = 1
    if not end_num:
        end_num = start_num
        start_num = 0
    while start_num < end_num:
        yield start_num
        start_num += step
for i in my_range(1, 100, 2):
    print(i)
for i in my_range(1, 5):
    print(i)
for i in my_range(10):
    print(i)

yield其他用法

>>> def index(name, food=None):
...     print(f'{name}准备干午饭!!!')
...     while True:
...         food = yield  # 在函数内可以采用表达式形式的yield
...         print(f'{name}正在吃{food}')
...

# 可以拿到函数的生成器对象持续为函数体send值
>>> res = index('kwan')  # 得到生成器对象
>>> res
<generator object index at 0x00000268F0FA6740>
>>> res.__next__()  # 需要事先“初始化”一次,让函数挂起在food=yield,等待调用res.send()方法为其传值
kwan准备干午饭!!!
>>> res.send('辣子鸡')  # 传值并自动调用__next__方法
kwan正在吃辣子鸡
>>> res.send('糖醋排骨')  # 传值并自动调用__next__方法
kwan正在吃糖醋排骨
>>> res.send('清蒸鱼')  # 传值并自动调用__next__方法
kwan正在吃清蒸鱼

生成器表达式

创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:

(表达式 for i in 可迭代对象 if 条件)

生成器表达式返回的是一个生成器对象,其优点是节省内存(一次只产生一个值在内存中)

>>> [x*x for x in range(3)]
[0, 1, 4]
>>> res = (x*x for x in range(3))
>>> res
<generator object <genexpr> at 0x101be0ba0>

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g) # 抛出异常StopIteration

题(掌握技巧)

>>> def add(n, i):  # 普通函数 返回两个数的和  求和函数
...     return n + i
...
>>>
>>> def test():  # 生成器
...     for i in range(4):
...         yield i
...
>>>
>>> g = test()  # 激活生成器
>>> for n in [1, 10]:
...     g = (add(n, i) for i in g)
...
"""
    第一次for循环
        g = (add(n, i) for i in g)
    第二次for循环
        g = (add(10, i) for i in (add(10, i) for i in g))
"""

>>> res = list(g)
>>> res
[20, 21, 22, 23]
posted @ 2022-07-11 19:55  梦想有双休  阅读(72)  评论(0编辑  收藏  举报