8-函数高级
函数高级使用
-
f:既是函数名称,也是指向函数的一个变量
-
所有指向函数的变量都可以调用该函数
-
回调函数
- m1(3, m2)
- m1是普通函数,m2作为参数,在m1内部调用m2
函数作用域
- 作用域:起作用的范围
- 局部变量与全局变量
- 局部变量:函数内部定义的变量,只能在函数内部使用
- nonlocal b
- 调用非本地(函数内部)的最近的b
- 优点:不会被外部干扰
- 缺点:内存会被回收(变量会被删除)
- 全局变量:函数外部定义的变量,具有全局作用域
- 默认不可以修改全局变量
- global 作用是a使用的是全局变量a
- global a
- 优点:内存不会被回收(变量不会被删除)
- 缺点:可能会被干扰
- 局部变量:函数内部定义的变量,只能在函数内部使用
函数嵌套和闭包
-
函数嵌套
-
def f1(): print('f1') def f2(): print('f2') # f2() return f2 res = f1() # res = f2 res() # 等价于f2()
-
传参
- f(3)(4)
-
-
函数闭包
-
闭包:函数嵌套,把内部函数返回,可以让外部函数中的参数或变量不被释放(让变量不消失)
-
闭包的特点:不会被外部干扰,内存也不会被回收
-
def out(): p = 10 def inner(): nonlocal p p += 1 print('p=', p) return inner f = out() # f = inner f() # 11,相当于inner() f() # 12 f() # 13
-
-
生成器扩展
- 生成器和迭代器很相似,其实它们都是消费者和生产者模型,都是用户通过next()方法来获得数据,而生成器和迭代器都是只有用户在调用next()时才返回数据。不同的是迭代器是通过自己实现next()方法来逐步返回数据,而生成器则使用yield自动完成了提供数据并且让程序进入wait状态,等待用户的进一步操作,所以生成器更加灵活和方便
- 生成器的方法
- next()方法
- send(msg)方法
- 当使用send(msg)发送消息给生成器时,wait_and_get会检测到这个信息,然后唤醒生成器,同时该方法获取msg并赋值给x
- g.send(5)
- throw()方法
- 生成器提供throw()方法从生成器内部来引发异常,从而控制生成器的执行
- h.throw(GeneratorExit)
- close()方法
- 当使用close()方法时,生成器会直接从当前状态退出
- 生成器的用途
- 节省内存
- 线性遍历访问数据
- 生成器可以将非线性化的处理转换成线性化的方式,典型的例子就是对二叉树的访问。传统的方法是使用递归函数来访问和处理,需要将处理方法放到访问的过程中,既容易出错也不清晰。比较好的方法是先将树的节点访问转换成线性,然后在外面遍历每一个节点,这样一来,处理每个节点的过程不需要放到访问每个节点的diamagnetic中去,更加清晰
列表生成器&列表生成式
-
列表生成式
- ages = [i * 10 for i in range(2, 5) if 2 < i < 4]
- l3 = [i+j for i in l1 for j in l2]
-
字典生成式
- d = {i: i+1 for i in range(1, 4)} #
-
列表生成器
-
ages = (i for i in range(5)) # <generator object <genexpr> at 0x0000015A66E54AC8>
-
生成器对象:可以不一次性占用太多的内存空间,我们一般需要一个一个元素取出来
-
next函数
-
print(next(ages)) # 0 print(next(ages)) # 1 print(next(ages)) # 2
-
-
生成器函数
- 生成器函数:在普通函数中包含yield关键字,则是生成器函数
- yield:
- 1.写在函数中,让普通函数变成生成器函数
- 2.可以返回值,但是不会退出函数
- 3.需要结合next使用,每次使用next,则会运行至下一个yield
-
计算代码耗时
-
计算代码耗时
-
import time start = time.time() # 获取当前时间 for i in range(1000): pass end = time.time() print(end - start)
-
可迭代对象&迭代器
-
from collections.abc import Iterable # 可迭代对象
-
from collections.abc import Iterator # 迭代器
-
可迭代对象
- 可迭代对象:只要可以使用for-in循环,就是可迭代对象
- 有:list, tuple, dict, set, str,generator
-
isinstance(): 检测某个对象是否属于某个类
- print(isinstance([1, 3], Iterable)) # True
-
迭代器
-
迭代器:既要能用for-in循环,且可以使用next调用
-
iter():将可迭代对象变成迭代器
-
l = [1, 3, 4] l2 = iter(l) print(l2) # <list_iterator object at 0x0000017DB5C4BE48> print(next(l2)) # 1 print(list(l2)) # [3, 4], 1已经被取出了
-
-
_iter_()将可迭代对象变成迭代器
-
l1 = [1, 3, 4] l1_iter = l1.__iter__() print(type(l1_iter)) # <class 'list_iterator'> for x in l1_iter: print(x)
-
-
偏函数
print(int('10'))
print(int('10', base=2)) # 2,将10看成是二进制
print(int('1010', base=8)) # 520
import functools
int2 = functools.partial(int, base=2)
print(int2('1010')) # 10