一、函数名的使用
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
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)
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慢
递归的应用场景:
在不明确要循环的次数时候,可以用递归
递归操作文件目录