Day11、迭代器、递归

时间:2022-10-04 22:37:50

一、函数名的使用

1.函数名的内存地址    

def func():
    pass

print(func)  # 函数的内存地址    <function func at 0x0000028C53141EA0>

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

def func():
    print(1)
a = func
a()
# func()   # 函数名可以当做值赋值给变量

3.函数名可以当做元素放到容器里

def func():
    print(1)

def func2():
    print(2)

li = [func,func2]
print(li)  # 函数名可以当做元素放到容器里
           #[<function func at 0x000001E2EC391EA0>, <function func2 at 0x000001E2EC56E950>]

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

def func():   
    print("吃了么")
def func2(fn):   
    print("我是func2")   
    fn()    # 执行传递过来的fn   
    print("我是func2")
func2(func)     # 把函数func当成参数传递给func2的参数fn.

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

def func_1():   
    print("这⾥是函数1")   
    def func_2():       
        print("这⾥是函数2")   
    print("这⾥里里是函数1")   
    return func_2
fn = func_1()  
# 执行函数1.  函数1返回的是函数2, 这时fn指向的就是上⾯面函数2
fn()    # 执行上面返回的函

二、闭包

1.一个嵌套函数

2.在嵌套函数的内部函数使用外部(非全局的变量)

满足以上两条就是闭包

内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数
函数内部定义的函数称为内部函数

def func1():
    name = "alex"
    def func2():
        print(name)
        # 闭包
    func2()
func1()
# 结果: alex
Day11、迭代器、递归Day11、迭代器、递归
def func():
    name = 'eva'
    def inner():
        print(name)
    return inner

f = func()
f()
函数外部调用函数内部的函数

 判断闭包函数的方法__closure__

def wrapper():
    a = 10
    def inner():
       print(a)
    print(inner.__closure__) # 不是None 就是闭包
    inner()
wrapper()
#   (<cell at 0x000001F2FD158468: int object at 0x00000000714F6D30>,)
#   10
money = 10
# 全局里存放会有污染和不安全的现象

def wrapper():
    money = 10
    def inner(num):
        nonlocal money
        money += num
        print(money)
    return inner
wrapper()(100)
Day11、迭代器、递归Day11、迭代器、递归
def wrapper():
    money = 1000
    def func():
        name = 'eva'
        def inner():
            print(name,money)
        return inner
    return func

f = wrapper()
i = f()
i()
闭包的嵌套

python中闭包,会进行内存驻留, 普通函数执行完后就销毁了

全局里存放会有污染和不安全的现象

面试必问,装饰器 -- 装饰器的本质就是闭包

闭包有个弊端:会出现内存泄漏

 

三、迭代器

1.1什么是可迭代对象?   Iterable: 可迭代对象. 内部包含__iter__()函数

字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

1.2可迭代协议

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

可迭代的:内部必须含有一个__iter__方法。

li = [1,2,3]
a = li.__iter__()
print(a.__next__())
print(a.__next__())  #一个一个取
print(a.__next__())

b = li.__iter__()
print(b.__next__())
print(b.__next__())
print(b.__next__())

 

 

 

1.3迭代器    Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

for循环,能遍历一个可迭代对象,他的内部到底进行了什么?

  • 将可迭代对象转化成迭代器。(可迭代对象.__iter__())
  • 内部使用__next__方法,一个一个取值。
  • 加了异常处理功能,取值到底后自动停止。

迭代器特性:

    惰性机制

    不能从下向上走

    一次性的,用完就没了

li = [1,2,3,4,6,7,87,8,9,90,0,0,0,0,8,7,7,67,]
em = li.__iter__()
while 1:
    try:
        print(em.__next__())

    except StopIteration:
        break
dic = {'1':1}  # 8679250325822402967 = 1
print(hash('1'))
for i in range(10):
    print(i)

 

 

四、递归

自己调用自己本身

有明确结束条件

def func():
    print(1)
    func()
func()

超出了递归的最大层次

递归默认层次,官方说明 1000,实际测试 998/997/993

 

count = 0
def func():
    global count
    count += 1
    print(count)
    if count == 500:
        return
    func()
func()

 

 

def func(n):
    n+=1
    print(n)
    if n == 100:
        return
    func(n)
func(0)
def func(age):
    age = age + 1
    print(age)
    if age == 5:
        return
    func(age)
func(2)
def func(age):
    print(age)

def func1(age):
    print(age)
    func(age+1)

def func2(age):
    print(age)
    func1(age+1)
func2(2)

 

递归的效率比较低,尾递归的用时 和 for的用时 是一样的,比for慢

 

递归的应用场景:

    在不明确要循环的次数时候,可以用递归

    递归操作文件目录