day7-基础函数的学习(二)

过了元旦,加油鸭,冲鸭!!!闭包

闲话不说,开始今日份学习整理。函数

今日目录,今天的学习内容不是不少!学习

1.函数名的运用spa

2.闭包(重要)code

3.迭代器(重要)对象

 

 

开始今日份总结blog

1.函数名的运用内存

1.1函数名是一个特殊的变量utf-8

def func():
    print(666)   
print(func)
#结果
<function func at 0x000001C2D44E7F28>
#返回函数的内存地址

1.2函数名能够当作变量赋值it

def func():
    print(666)

func2 = func
f1 = func2
f2 = f1
f3 = f2
print(f3)
#结果,返回函数的内存空间
<function func at 0x0000020FA58B7F28>

1.3函数名能够当作容器类数据类型的元素

def func1():
    print('func1')

def func2():
    print('func2')

def func3():
    print('func3')

li =[func1,func2,func3]
for i in li:
    i()
#这样就能够一个一个的去调用函数了

1.4函数名能够当作函数的参数

def func(x):
    x()
    print('in func')

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

func(func1)
#结果
in func1
in func

1.5函数名能够当作函数的返回值

def func(x):  # x ---> func1
    return x  # func1

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

ret = func(func1)  # func1
ret()
#结果
in func1

2.闭包(重要)

定义:

  • 内层函数对于外层函数(非全局)变量的引用
  • 闭包值存在于内层函数内
  • 函数都要逐层返回,最终返回最外层的函数
  • (我的理解)在函数外部能够调用函数内部,同时可使用内部的值

闭包的肯定

#不是闭包
name = 'test'
def func1():
    def inner():
        print(name)
    return inner()

f = func1()
print(f.__closure__[0].cell_contents)

#结果
AttributeError: 'NoneType' object has no attribute '__closure__'
#表示函数内没有闭包的参数

#是闭包
# 闭包
def func():
    age =18
    name ='test'
    def inner():
        print(age)
        print(name)
    return inner
f = func()

# 获取闭包引用的外层变量
print(f.__closure__[0].cell_contents)
print(f.__closure__[1].cell_contents)
#结果
18
test

闭包的用法

需求,输入一个数,连续自加这个数五次,有可能会写成这样

def func(step):
    sum = 1
    sum += step
    print(sum)
i =0
while i <5:
    func(3)
    i+=1
#结果
4
4
4
4
4

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

从新写一下上面这个需求

def func(step):
    sum1 = 1
    def inner():
        nonlocal sum1
        sum1 += step
        print(sum1)
    return inner
i =0
f =func(3)
while i <5:
    f()
    i+=1
#结果
4
7
10
13
16

须要注意的是,若是将f =func(3)放入下面循环内部,就会发现打印的都是4,缘由呢,就是生产了五个闭包,每一个闭包执行了一次。

闭包的经常使用使用环境

  • 装饰器
  • 爬虫的一些使用环境(对一个网页重复抓取,以前抓取的内容已经放在内存中)

3.迭代器(重要)

3.1可迭代对象

经常使用可迭代对象为:str  list tuple set range() 文件句柄

可迭代对象:内部含有__iter__方法的就是可迭代对象,遵循可迭代协议,可迭代对象不能直接取值

判断是不是可迭代对象

# 方法一:

s1 = 'barry'
# print('__iter__' in dir(s1))
# print('__iter__' in dir(range(10)))

3.2迭代器

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

可迭代对象转化成迭代器

可迭代对象.__iter__() 或者 iter(可迭代对象)

s1 = 'abcd'
obj = iter(s1)
print(obj)
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
print(obj.__next__())
#  一个next 对应一个值,一一对应。
#结果
a
b
c
d
    print(obj.__next__())
StopIteration

判断

一个对象是是迭代器

#方法一:判断一个对象内有没有指定的方法
li =[1,2,3,4]
obj = iter(li)
print('__iter__'in dir(obj) and '__next__'in dir(obj))
#结果
True
#方法二:引入其余模块,进行判断
from collections import Iterable
from collections import Iterator
li =[1,2,3,4]
obj = iter(li)
print(isinstance(obj,Iterable))#判断是不是可迭代对象
print(isinstance(obj,Iterator))#判断是不是迭代器
#结果
True
True
#这个也能够用于判断上面是不是可迭代对象

type() isinstance()区别?
type()只是判断该对象的数据类型
isinstance()不只能够判断该对象的数据类型,并且能够判断其余不少

迭代器的做用:
1,节省内存.
2,惰性机制.
3, 一条路走到黑,不走回头路.
s2 = [1, 2, 3, 4, 5]
obj2 = iter(s2)
print(next(obj2))
print(next(obj2))

练习

 

# 练习
# 判断一个对象是不是可迭代对象,迭代器
# str list tuple set dict range() 文件句柄
# f = open('file',encoding='utf-8',mode='w')
# print(isinstance(f,Iterator))

# s2 = [1, 2, 3]
# # 将s2转化成迭代器 进行取值
# obj2 = iter(s2)
# # print(obj2.__next__())
# print(next(obj2))

#while循环模拟for循环机制