迭代器相关

1 函数名的使用以及第一类对象

函数名就是一个变量,命名规范与变量一致(8条)但它是一个特殊的变量,与()配合可以调用函数的变量.

<1>函数名的内存地址.

def func():
    print("haha")
print(func)     #答案<function func at 0x0000021406756048>是函数名func的内存地址

<2>函数名可以赋值给其它变量

def  func():
    print("haha")
print(func) #打印变量func内存地址
ret=func #把函数名func赋值给变量ret
ret() #ret()相当于func(),即调用函数func

<3>函数名可以当做容器类的元素,即可以当做列表中的元素进行储存

def func():
    pass
def func_1():        
    pass
lst=[func,func1]
for i in lst:
i()

<4>可以作为参数传递给函数

def func():        
    pass
def proxy(fn):
    fn()  #调用fn函数,即如果func传递进来以后就调用func函数.
proxy(func) #调用proxy函数,把func传递到fn位置

<5>可以作为函数的返回值.

def outer():
    pass
    def inner():
        pass
    return inner #返回 inner
outer()() #第一个括号调用outer函数,返回inner,第二个括号相当于inner(),即调用inner函数.

2闭包

闭包就是内层函数对外层函数(非全局)变量的引用.也就是说在内层函数中访问外层函数的局部变量.

作用:1可以保护你的变量不受侵害

  2可以让一个变量常驻

完整的闭包函数格式
def func():
    a=12
    def inner():
    print(a)
    return inner

我们可以用__closure__来检测函数是不是闭包.返回cell就是闭包,返回None就不是闭包.

def func():
    a=12
    def inner():
        print(a)
    return inner
print(func().__closure__)# 结果(<cell at 0x0000016801C67588: int object at 0x0000000050496D70>,)

好处:原来我们说过,如果在外层函数中访问过内层函数,那么内层函数将会被销毁.在闭包中如果内层函数被销毁,将不能正常执行.所以Python中规定,如果你在内部函数中访问了外层函数中的变量,那么这个变量将不会被销毁,常驻内存中.也就是说,使用闭包,可以保证外层函数中的变量在内存中常驻.

极其简易爬虫代码:

from urllib.request import urlopen
def but():
    content=urlopen("http://www.xiaohua100.cn/").read() # 获取网页内容
    def get_content():
        return content
    return get_content
ret = but() #这个时候 执行but()就开始执行校花100的内容了,后面再用到这里的内容就不需要执行非常繁琐的网络连接
el = ret()  #获取内容
print(el)
el1 =ret()  # 再次获取内容
print(el1)

  

3迭代器

<1>可迭代对象:str list tuple dict set.因为它们遵守了可迭代协议,所以为可迭代对象.

<2>如何查询是不是可迭代(dir),寻找__iter__ 如果能找到. 那么这个类的对象就是⼀一个可迭代对象.可以执行for循环.

print(dir(str)) #查看str(字符串)可以执行哪些操作,方法#['__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']

  我们还可以通过isinstance函数来查看一个对象是什么数据类型的.

l = [1,2,3]
l1=l.__iter__() # 获取l的迭代器
from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable))  # True 是否可迭代
print(isinstance(l,Iterator))  # False 是否是迭代器
print(isinstance(l1,Iterable)) # True
print(isinstance(l1,Iterator)) # True

<3>可迭代对象:Iterable 里面有__iter__()

  迭代器:iterator 里面有 __iter__()和__next__()

  迭代器特点:1只能向前2惰性机制3节省内存

<4>for循环

内部机制:    1使用__iter__获取迭代器

      2使用while循环与__next__来获取数据

      3处理异常 try *** except StopIteration

数据结构 :
it=xx.__iter__()
while 1:
    try:
        data=it.__next__()
    except Stopiteration:
        break

例子:

l=[1,2,3]
l1=l.__iter__()
while 1:
    try:
        data=l1.__next__()
        print(data)
    except StopIteration:
        break
# 结果1
 2
 3

   我们可以把要迭代的内容当成⼦子弹. 然后呢. 获取到迭代器__iter__(), 就把⼦子弹都装在弹夹 中.  然后发射就是__next__()把每⼀一个⼦子弹(元素)打出来. 也就是说, for循环的时候. ⼀一开始的 时候是__iter__()来获取迭代器. 后⾯面每次获取元素都是通过__next__()来完成的. 当程序遇到 StopIteration将结束循环.  

我们可以把要迭代的内容当成子弹,然后,获取到迭代器__iter__()相当于把子弹装在弹夹中,__next__()就是把每一子弹打出来,for循环的时候也是一开始__iter__()获取迭代器,后面循环出的每一个元素都是通过__next__()来完成的,程序遇到StopIteration结束循环.

原文地址:https://www.cnblogs.com/lingcai/p/9456957.html