闭包和迭代器

Posted zhaodingding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包和迭代器相关的知识,希望对你有一定的参考价值。

 

技术分享图片

一.函数名的运用

  函数名是一个变量, 但它是一个特殊的变量, 与括号配合可以执行函数的变量.

1. 函数名的内存地址

技术分享图片

2. 函数名可以赋值给其他变量

 技术分享图片

3. 函数名可以当做容器类的元素 

 

技术分享图片

 技术分享图片

 

 4. 函数名可以当做函数的参数

技术分享图片

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

 技术分享图片

 

def panpan():
    print("我是潘潘. 我喜欢毒丈夫 ")

def xiaoping():
    print("我是小萍萍. 我喜欢毒丈夫 ")

def xiaohua():
    print("我是小花花. 我喜欢毒丈夫 ")

def daguanren():
    print("大官人喜欢xxxx")

def wangpo(nv, nan): # 核心业务逻辑
    nv()
    nan()

wangpo(xiaohua, daguanren) # 王婆代理了大官人和潘潘
def play(wanjv1, wanjv2, wanjv3):
    ‘‘‘
        玩儿函数
        :param wanjv1: 玩具1
        :param wanjv2: 玩具2
        :param wanjv3: 玩具3
        :return: 开心
    ‘‘‘
    print("我要玩儿荡秋千")
    return "开心"


# play("独木桥", "独轮车", "独眼龙")
print(play.__doc__) #  document
print(str.join.__doc__)

 

 二. 闭包

def func():
    a = 10
    print(a)
func()
print(a) # 在外面你是访问不到局部变量的, 局部变量是安全的


# 全局变量可能会被修改, 全局变量是不安全的. 可能会被其他函数所更改
a = 10
def func():
    global a
    a = 20
    print(a)
func()
print(a)

# 用闭包可以保护我们的变量
# 写法: 在外层函数中声明一个变量. 在内层函数使用或者返回这个变量.
# 这个结构叫闭包
# 1.可以保护我的变量
# 2.可以让一个变量常驻内存

 

什么是闭包? 闭包就是内层函数, 对外层函数(非全局)的变量的引用. 叫闭包

 技术分享图片

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

 技术分享图片

问题, 如何在函数外边调用内部函数呢?

技术分享图片

 

 那如果多层嵌套呢? 很简单, 只需要一层一层的往外层返回就行了

 技术分享图片

由它我们可以引出闭包的好处. 由于我们在外界可以访问内部函数. 那这个时候内部函
数访问的时间和时机就不一定了, 因为在外部, 我可以选择在任意的时间去访问内部函数.
个时候. 想一想. 我们之前说过, 如果这个函数执行完毕. 则这个函数中的变量以及局部命名
空间中的内容都将会被销毁. 在闭包中. 如果变量被销毁了. 那内部函数将不能正常执行.
. python规定. 如果你在内部函数中访问了外层函数中的变量. 那么这个变量将不会消亡.
将会常驻在内存中. 也就是说. 使?闭包, 可以保证外层函数中的变量在内存中常驻. 这样做
有什么好处呢? 非常大的好处. 我们来看这个关于爬虫的代码 :

from urllib.request import urlopen

def func():
    # 闭包. content会常驻内存
    content = urlopen("http://www.xiaohuar.com/").read()
    def inner():
        return content
    return inner

print("加载中...")
g = func() # 网络请求
print("加载完毕")
print(g())
print(g())
print(g())

. 迭代器

 我们之前一直在用可迭代对象进行迭代操作. 那么到底什么是可迭代对象. 这个主要讨
论可迭代对象. ?先我们先回顾一下之前我们所熟知的可迭代对象有哪些:
str, list, tuple, dict, set. 那为什么我们可以称他们为可迭代对象呢? 因为他们都遵循了可
迭代协议. 什么是可迭代协议. 首先我们先看一段错误代码:

技术分享图片

注意看报错信息中有这样一句话. ‘int‘ object is not iterable . 翻译过来就是整数类型对象
是不可迭代的. iterable表?可迭代的. 表示可迭代协议. 那么如何进行验证你的数据类型是否
符合可迭代协议. 我们可以通过dir函数来查看类中定义好的所有方法 

技术分享图片

在打印结果中. 寻找__iter__ 如果能找到. 那么这个类的对象就是一个可迭代对象

 技术分享图片技术分享图片

我们发现在字符串中可以找到__iter__. 继续看一下list, tuple, dict, set

 

技术分享图片
[__add__, __class__, __contains__, __delattr__, __dir__,
__doc__, __eq__, __format__, __ge__, __getattribute__,
__getitem__, __getnewargs__, __gt__, __hash__, __init__,
__init_subclass__, __iter__, __le__, __len__, __lt__, __mul__,
__ne__, __new__, __reduce__, __reduce_ex__, __repr__, __rmul__,
__setattr__, __sizeof__, __str__, __subclasshook__, count,
index]
[__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]
[_CHUNK_SIZE, __class__, __del__, __delattr__, __dict__,
__dir__, __doc__, __enter__, __eq__, __exit__, __format__,
__ge__, __getattribute__, __getstate__, __gt__, __hash__,
__init__, __init_subclass__, __iter__, __le__, __lt__, __ne__,
__new__, __next__, __reduce__, __reduce_ex__, __repr__,
__setattr__, __sizeof__, __str__, __subclasshook__, _checkClosed,
_checkReadable, _checkSeekable, _checkWritable, _finalizing,
buffer, close, closed, detach, encoding, errors, fileno,
flush, isatty, line_buffering, mode, name, newlines, read,
readable, readline, readlines, seek, seekable, tell,
truncate, writable, write, writelines]
[__and__, __class__, __contains__, __delattr__, __dir__,
__doc__, __eq__, __format__, __ge__, __getattribute__, __gt__,
__hash__, __iand__, __init__, __init_subclass__, __ior__,
__isub__, __iter__, __ixor__, __le__, __len__, __lt__,
__ne__, __new__, __or__, __rand__, __reduce__, __reduce_ex__,
__repr__, __ror__, __rsub__, __rxor__, __setattr__, __sizeof__,__str__, __sub__, __subclasshook__, __xor__, add, clear,
copy, difference, difference_update, discard, intersection,
intersection_update, isdisjoint, issubset, issuperset, pop,
remove, symmetric_difference, symmetric_difference_update, union,
update]
[__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]
list, tuple, dict, set

我们发现这一个可以进行for循环的东西都有__iter__函数, 包括range也有. 可以试一试
.
这是查看这个对象是否是可迭代对象的第一种办法. 我们还可以通过isinstence()函数来查
看这个对象是什么类型的

技术分享图片

 

技术分享图片
l = [1,2,3]
l_iter = l.__iter__()
from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable)) #True
print(isinstance(l,Iterator)) #False
print(isinstance(l_iter,Iterator)) #True
print(isinstance(l_iter,Iterable)) #True
isinstance

综上. 我们可以确定. 如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议.
就可以获取到相应的迭代器. 这个的__iter__是帮助我们获取到对象的迭代器. 我们使用迭代
器中的__next__()来获取到?个迭代器中的元素. 那么我们之前讲的for的工作原理到底是什
? 继续看代码

技术分享图片
lst = [1,2,3]
it = lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())

# 重新拿一个迭代器
it = lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())
原理

技术分享图片

for循环的机制

for i in [1,2,3]:
print(i)

 使用while循环+迭代器来模拟for循环(必须要掌握)

 

lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
try:
i = lst_iter.__next__()
print(i)
except StopIteration:
break
#  总结
# 特点:
# 1. 节省内存
# 2. 惰性机制
# 3. 只能向前. 不能反复
# 小总结
# Iterable: 可迭代对象. 里面包含了__iter__(),可以使用for循环
# Iterator: 迭代器. 里面包含了__iter__() 和 __next__(), 也可以使用for循环

# from collections import Iterable # 可迭代的
# from collections import Iterator # 迭代器

 
















































以上是关于闭包和迭代器的主要内容,如果未能解决你的问题,请参考以下文章

Rust编程语言入门之函数式语言特性:-迭代器和闭包

11 第一类对象 闭包 迭代器

python 闭包和迭代器

python之函数闭包可迭代对象和迭代器

笔记---迭代器,闭包,装饰器

Python概念之装饰器迭代器生成器