day 10 函数名的运用,闭包,迭代器

函数名的本质

函数名本质上就是函数的内存地址

函数名的五种运用:

 1、函数名是一个变量

def func():
    print(666)
print(func)    # 函数的内存地址 <function func at 0x000002B6D2559AE8>

2、函数名可以当做变量赋值

def func():
    print(666)
f1 = func
f2 = f1
f2()                

3、函数名可以当做容器类数据类型的元素

复制代码
def func1():
    print(111)
def func2():
    print(222)
def func3():
    print(333)
l1 = [func1, func2 ,func3]
for i in l1:
    i()
复制代码

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

def func(x):   #  x  == func1
    x()
    print('in func')
def func1():
    print('in func1')
func(func1)

5、函数名可以当做函数的返回值

复制代码
def func(x):  # x ---> func1
    return x  # func1

def func1():
    print('in func1')

ret = func(func1)  #  ret = func1
ret()     # func1()
func(func1)()  # x() == func1()
复制代码

满足3,4,5 函数名也称为第一类对象

闭包:

什么是闭包:

复制代码
def func():
    name = 666
    print(111)
    def func1():
        print(name)  # 这就是闭包, 内层函数对外层函数(非全局)变量的引用
    func1()
func()
复制代码
1,内层函数对外层函数(非全局)变量的引用。
2,闭包只存在于内层函数中。
3,函数都要逐层返回,最终返回给最外层函数。
复制代码
def func():
    name = 'alex'
    def inner():
        print(name)
    return inner           
f = func()    #  f = inner
f()
复制代码

闭包的判断

f.__closure__[0].cell_contents   闭包引用的外部变量
复制代码
def func():
    name = 'alex'
    age = 19
    def inner():
        print(name)
        print(age)
    return inner
f = func()         # 定义f,因为f是闭包
# 获取闭包引用的外层变量,如果不是闭包则报错
print(f.__closure__[0].cell_contents)  #固定用法  19
print(f.__closure__[1].cell_contents)  # alex
复制代码

闭包有什么用?

闭包:解释器执行程序时,如果遇到函数,随着函数的结束而关闭临时名称空间,但是!!!如果遇到闭包,有一个机制:那么闭包的空间不会随着函数的结束而关闭。

复制代码
def wrapper(step):
    num =1
    def inner():
        nonlocal num
        num += step
        print(num)     # 输出 4   7   10  13  16
    return inner
f = wrapper(3)
j = 0
while j < 5:
    f()
    j += 1
复制代码

闭包就是在内存中开一个空间,常贮存一些内容,以便后续程序调用
闭包的应用:
1、装饰器
2、爬虫

迭代对象:
iterable: 可迭代对象
内部含有__iter__方法的就是可迭代对象,遵循可迭代协议
s1 = 'barry'
l1 = [1, 2, 3]
print('__iter__' in dir(s1))  # True  是可迭代对象

可迭代对象不能直接取值(含索引的迭代对象除外) ,需要转换成迭代器才能取值

迭代器

迭代器:内部含有'__iter__'并且含有'__next__'方法的就是迭代器,遵循迭代器协议。

可迭代对象转换成迭代器:

  可迭代对象.__iter__()

  obj = iter(可迭代对象)

判断一个一个对象是否是迭代器(含iter,next)或迭代对象

 方法一:  看__iter__ , __next__  在不在dir() 里面

s1 = 'abcdefg'
obj = iter(s1)    # 将s1转换成迭代器
print('__iter__' in dir(s1))   # True
print('__iter__' in dir(obj))  # True
print('__iter__' in dir(s1) and '__next__' in dir(s1))  # False
print('__iter__' in dir(obj) and '__next__' in dir(obj)) # True
方法二:   isinstance(obj, Iterable/Iterator)
复制代码
s1 = 'abcdefg'
obj = iter(s1)    # 将s1转换成迭代器
from collections import Iterable   # 迭代对象
from collections import Iterator   # 迭代器
print(isinstance(obj,Iterator))  # 判断obj是否为迭代器     True
print(isinstance(obj,Iterable))  # 判断obj是否为可迭代对象 True
print(isinstance(s1,Iterator))   # 判断obj是否为迭代器     False
print(isinstance(s1,Iterable))   # 判断obj是否为可迭代对象 True
复制代码
 

迭代器取值

s2 = [1, 2, 3]
obj = iter(s2)
print(obj.__next__())    # 方法一
print(next(obj))            # 方法二
type() isinstance()区别?

# type()只是判断该对象的数据类型
# isinstance()不仅可以判断该对象的数据类型,而且可以判断其他很多

迭代器的作用:
1、节省内存
2、惰性机制 (netx())一下,出一个值
3、一条路走到黑,不走回头路

While循环模拟for循环机制
复制代码
l1 = [i for i in range(10)]
obj = iter(l1)
while 1:
    try:     # 试一试,如果报错就执行下面的命令
        print(next(obj))
    except StopIteration:  
        break
复制代码



 

猜你喜欢

转载自www.cnblogs.com/malimalihong95/p/10211272.html