码迷,mamicode.com
首页 > 其他好文 > 详细

闭包和迭代器

时间:2018-09-18 19:55:32      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:urllib   display   18C   内部函数   dir   move   现在   global   instance   

 

技术分享图片

一.函数名的运用

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

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 # 迭代器

 

闭包和迭代器

标签:urllib   display   18C   内部函数   dir   move   现在   global   instance   

原文地址:https://www.cnblogs.com/zhaodingding/p/9670929.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!