09_Python迭代器_全栈开发学习笔记

2019-01-07  本文已影响0人  豆行僧

1. 迭代器原理

1.1 dir()

dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法dir(),该方法将被调用。如果参数不包含dir(),该方法将最大限度地收集参数信息。

范例1:

print(dir([]))    # 告诉我列表拥有的所有方法
print(dir({}))    # 告诉我字典拥有的所有方法
print(dir(''))    # 告诉我字符串拥有的所有方法
print(dir(range(10)))    # 告诉我range()拥有的所有方法

执行结果:

['__add__', '__class__', '__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']
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']

范例2:

ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10)))
print(ret)    # 求上述四种类型中共有的方法(求交集)

执行结果:

{'__contains__', '__sizeof__', '__lt__', '__gt__', '__eq__', '__getitem__', '__class__', '__le__', '__str__', '__new__', '__init_subclass__', '__reduce_ex__', '__dir__', '__reduce__', '__delattr__', '__ne__', '__repr__', '__ge__', '__subclasshook__', '__format__', '__iter__', '__len__', '__doc__', '__init__', '__hash__', '__getattribute__', '__setattr__'}

1.2 双下方法

范例1:

print([1].__add__([2]))    # 等同于第二行
print([1]+[2])    # 等同于第一行

执行结果:

[1, 2]
[1, 2]

范例2:
只要是能被for循环的数据类型 就一定拥有__iter__方法

# 判断各类型是否含有__iter__方法
print('__iter__' in dir(int))
print('__iter__' in dir(bool))
print('__iter__' in dir(list))
print('__iter__' in dir(dict))
print('__iter__' in dir(set))
print('__iter__' in dir(tuple))
print('__iter__' in dir(enumerate([])))
print('__iter__' in dir(range(1)))

执行结果:

False
False
True
True
True
True
True
True

1.3 引出迭代器

一个列表执行了__iter__()之后的返回值就是一个迭代器
范例1:

print([].__iter__())

执行结果:

<list_iterator object at 0x000001A65E641898>

范例2:
查看两者的方法

print(dir([]))
print(dir([].__iter__()))

执行结果:

['__add__', '__class__', '__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']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']

范例3:
查看迭代器独有的方法

print(set(dir([].__iter__())) - set(dir([])))

print([1,'a','bbb'].__iter__().__length_hint__())  #元素个数

l = [1,2,3]
iterator = l.__iter__()
print(iterator.__next__()) # 用__next__方法一个一个取值
print(iterator.__next__())
print(iterator.__next__())

执行结果

{'__setstate__', '__next__', '__length_hint__'}

3

1
2
3

1.4 小结与概念

Iterable 可迭代的 -- > __iter__ #只要含有__iter__方法的都是可迭代的
[].__iter__() 迭代器 -- > __next__ #通过next就可以从迭代器中一个一个的取值

可迭代协议:只要含有 __iter__ 方法的都是可迭代的
迭代器协议:内部含有 __next____iter__ 方法的就是迭代器

1.4.1 证明迭代器协议

范例1:

print('__iter__' in dir( [].__iter__()))
print('__next__' in dir( [].__iter__()))

执行结果:

True
True

范例2:
isinstance()方法

from collections import Iterable    # 可迭代的
from collections import Iterator    # 迭代器
print(isinstance([],Iterator))    # 使用isinstance判断列表是不是一个迭代器
print(isinstance([],Iterable))    # 使用isinstance判断列表是不是一个可迭代的

执行结果:

False    # 列表不是迭代器
True    # 列表是可迭代的

1.5 可迭代概念

迭代器协议 —— 内部含有 __next____iter__ 方法的就是迭代器

迭代器协议和可迭代协议
可以被for循环的都是可迭代的
可迭代的内部都有 __iter__ 方法
只要是迭代器 一定可迭代
可迭代的 .__iter__() 方法就可以得到一个迭代器
迭代器中的 __next__() 方法可以一个一个的获取值

for循环其实就是在使用迭代器

判断别人写的函数是否是迭代器

  1. iterator
    print([].iter())
  1. 可迭代对象
    print(range(10))
  1. 直接给你内存地址

for
只有 是可迭代对象的时候 才能用for
当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代

范例:
for循环做得事情(for循环的工作原理)

for i in l:
    pass

# for循环实际工作步骤如下:
# iterator = l.__iter__()
# iterator.__next__()

1.6 迭代器的好处

  1. 从容器类型中一个一个的取值,会把所有的值都取到。
  2. 节省省内存空间(range与文件句柄)
       迭代器并不会在内存中再占用一大块内存,
          而是随着循环每次生成一个;
          每次next每次给我一个。

1.7 模仿for循环写自己的迭代器例子

范例:

l = [1,2,3,45]
iterator = l.__iter__()
while True:
    print(iterator.__next__())

执行结果:

1
Traceback (most recent call last):
2
  File "E:/python_project/muggle/muggle_test.py", line 6, in <module>
3
45
    print(iterator.__next__())
StopIteration
# 上述报错为正常,以后会学到如何消除报错

2. 迭代器复习

# 迭代器和生成器
# 迭代器
    # 可迭代协议 —— 含有iter方法的都是可迭代的
    # 迭代器协议 —— 含有next和iter的都是迭代器
    # 特点
        # 节省内存空间
        # 方便逐个取值,一个迭代器只能取一次。
上一篇下一篇

猜你喜欢

热点阅读