闭包和迭代器

一.函数名的运用

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

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

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

时间: 2024-10-29 10:07:04

闭包和迭代器的相关文章

python 闭包和迭代器

主要内容: 1. 函数名的使用以及第?类对象 2. 闭包 3. 迭代器 1. 函数名的使用以及第?类对象   函数名是一个变量, 但它是一个特殊的变量, 与括号配合可以执行函数的变量. (1) 函数名的内存地址 def func(): print("呵呵") print(func) #<function func at 0x000001EBCE5D6048> (2)函数名可以赋值给其他变量 def func(): print("呵呵") print(fu

第十一天 函数名的使用以及第一类对象, 闭包, 迭代器

本节主要内容: 1.函数名的使用以及第一类对象 2.闭包 3.迭代器 一.函数名的运用 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量 1.函数名的内存地址: 2.函数名可以赋值给其他变量 3.函数名可以当作容器类的元素(作为list元素) 4.函数名可以当作函数的 5.函数名可以作为函数的返回值 二.闭包 什么是闭包: 闭包就是内层函数, 对外层函数(非全局)的变量的引用. 叫闭包 在内存函数中调用了外层函数的变量,叫闭包.可以让一个局部变量常驻内存 使用__closur

python函数名的应用、闭包和迭代器

一.函数名的应用(第一类对象) 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数变量. 1.函数名的内存地址 def func(): print("哈哈") print(func) #<function func at 0x000002750A7998C8> 2.函数名可以赋值给其他变量 def func(): print("哈哈") print(func) a = func #把函数当成一个变量赋值给另一个变量 a() #函数调用 fun

函数名的运用(第一类对象)以及闭包与迭代器

一.函数名的应用(第一类对象) 1.函数的命名规范和变量是一样的,函数名其实就是变量名. 2.函数名的内存地址 def func(): print("呵呵" print(func) 结果: <function func at 0x1101e4ea0> 3.函数名可以赋值给其他变量 def func(): print("呵呵") print(func) a = func # 把函数当成一个变量赋值给另一个变量 a() # 函数调用 func() 结果: &

python之函数名,闭包、迭代器

一.函数名的运用(第一类对象) 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量. 1,函数名的内存地址: def func(): print("呵呵") print(func) # 结果为:<function func at 0x00000000029299D8> 打印出func的内存地址 2,函数名可以赋值给其他变量: def func(): print("呵呵") a = func # 把函数当成一个变量赋值给另一个变量 a()

DAY11 函数进阶(函数名的本质,闭包,迭代器)

函数名的本质与一级对象: 1.函数名表示函数的内存地址. 2.函数名可以赋值给变量,可以作为容器数据类型的元素. 3.函数名可以作为参数传递给函数. 4.函数名可以作为函数的返回值. #一. 函数名表示函数的内存地址 def func(): print(111) print(func) >>><function func at 0x00000199DFD22F28> #二.函数名可以赋值给变量,可以作为容器数据类型的元素. def func(): print(111) f =

闭包,迭代器,生成器,列表推导式

1:函数名的应用   1, 函数名就是函数的内存地址.    2, 函数名可以作为变量.    3, 函数名可以作为函数的参数.    4, 函数名可以作为容器类类型的元素.    5,函数名可以当做函数的返回值. 2:globals() locals() globals() # 返回全局变量的一个字典. locals()  返回 当前位置 的局部变量的字典. 1 name = 'leiwenxuan' 2 def fun(): 3 a = 2 4 b = 3 5 6 print(globals

闭包、迭代器

1.函数名 函数名就是变量名(可以进行赋值),函数名存储的是函数的地址 需要括号才可以执行 2.闭包:内层函数对外层函数(非全局)变量的引用 作用:1.保护一个变量,让他不受改变 2.让一个变量常驻内存 使?__closure__来检测函数是否是闭包. 使?函数名.__closure__返回cell就是 闭包. 返回None就不是闭包 3.Iterable (可迭代的) Iterator(迭代器) d7ir() 查看变量能够执行的方法(内置函数) dir(str)) # 查看str能够执行的操作

第一类对象(函数),闭包及迭代器

第一类对象 函数对象对象可以像变量一样进行赋值 还可以作为列表的元素进行使用 可以作为返回值返回 可以作为参数进行传递 def wrapper(): def inner(): print("alex") return inner # 可以返回函数名 ret = wrapper() ret() # 在函数外访问函数内的函数 闭包 闭包(函数的嵌套) 内层函数对外层函数中的变量的使用 好处: 1. 保护变量不被侵害 2. 让一个变量常驻内存 如何通过代码查看一个闭包 __closure__