20 函数:内嵌函数和闭包
一、内嵌函数
>>> def fun1(): print('fun1()正在被调用...') def fun2(): print('fun2()正在被调用...') fun2() >>> fun1() fun1()正在被调用... fun2()正在被调用...
【注意①】内嵌函数只能在外部函数的范围内起作用!
【容易错误】:
>>> def fun1(): print('fun1()正在被调用...') def fun2(): print('fun2()正在被调用...') >>> fun1() fun1()正在被调用...
二、闭包 __
如果在一个内部函数里,对外部函数的作用域内(但不是在全局作用域)的变量进行引用,那么这个内部函数就被认为是闭包。
就是能够读取其他函数内部变量的函数。>>> def FunX(x): #定义FunX()的范围就是外部作用域,x就是外部作用域的变量 def FunY(y): #FunY()就是FunX()的内部函数 return x * y #FunY()对x进行引用 return FunY '''达到以上三点要求,FunY()就是个闭包'''
【易错】内部函数返回值不要写【FunY()】,否则:
>>> def FunX(x): def FunY(y): return x * y return FunY() >>> FunX(2)(3) Traceback (most recent call last): File "<pyshell#17>", line 1, in <module> FunX(2)(3) File "<pyshell#16>", line 4, in FunX return FunY() TypeError: FunY() missing 1 required positional argument: 'y'
来试一下:
>>> i = FunX(8) >>> i <function FunX.<locals>.FunY at 0x0000021F59727F28> >>> type(i) <class 'function'> >>> i(5) 40 >>> FunX(8)(5) 40
【注意】但是不可以在外部函数的外边对内部函数进行调用:
>>> FunY(5) Traceback (most recent call last): File "<pyshell#48>", line 1, in <module> FunY(5) NameError: name 'FunY' is not defined
【注意】在内部函数中,只能对外部函数进行调用,不可以进行修改:
>>> def Fun1(): x = 5 def Fun2(): x *= x return x return Fun2() >>> Fun1() Traceback (most recent call last): File "<pyshell#60>", line 1, in <module> Fun1() File "<pyshell#59>", line 6, in Fun1 return Fun2() File "<pyshell#59>", line 4, in Fun2 x *= x UnboundLocalError: local variable 'x' referenced before assignment
【错误原因】对于【Fun2()】,【x = 5】是外部的变量,而在【Fun2()】内的【x *= x】是
试图改变外部的变量【x】的值,肯定就是不行的。
【解决办法①】变成列表,可变对象(进行容器改造)
>>> def Fun1(): x = [5] def Fun2(): x[0] *= x[0] return x[0] return Fun2() >>> Fun1() 25
【解释】当将【x = 5】变成列表【x = [5]】时,【x】的值就不是储存在【Fun2()】的外部函数中了。此时【x】可变,因为是列表。
【解决办法②】用关键字【nonlocal】将【x】升级成非局部变量
>>> def Fun1(): x = 5 def Fun2(): nonlocal x x *= x return x return Fun2() >>> Fun1() 25
21 函数:lambda表达式
【原语句①】
>>> def ds(x): return 2 * x + 1 >>> ds(5) 11
【lambda语句①】
>>> lambda x : 2 * x + 1 <function <lambda> at 0x000001C7D0A078C8> >>> ds = lambda x : 2 * x + 1 >>> ds(5) 11
【原语句②】
>>> def add(x, y): return x + y >>> add(3, 4) 7
【lambda语句②】
>>> lambda x, y : x + y <function <lambda> at 0x000001C7D0A07C80> >>> a = lambda x, y : x + y >>> a(3, 4) 7
一、lambda表达式的作用
1.python写一些执行脚本时,使用lambda就可以省下定义函数的过程,比如说我们只是需要写个简单的脚本来管理服务器时间,我们就不需要专门定义一个函数然后再写调用,使用lambda就可以使得代码更加精简。
2.对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数起个名字也是比较头疼的问题,使用lambda就不需要考虑命名的问题了。
3. 简化代码的可读性,由于普通的屌丝函数阅读经常要调到开头的def定义部分,使用lambda函数可以省去这样的麻烦
二、两个比较牛逼的BIF(内置函数)
(一)filter() __过滤器
1、两个参数,(function or None, iterable)
有两个参数,第二个参数为可迭代的数据,第一个参数可以为None或者函数,当为None时,将iterable中为真的数据挑选出来,当为function时,将iterable中满足function的结果为真的数据挑选出来。
1)当(None, iterable)时,过滤掉【iterable】中的【非True】内容:>>> filter(None, [1, 0, False, True]) <filter object at 0x000001C7D0A13CF8> >>> list(filter(None, [1, 0, False, True])) [1, True]
2)当(function, iterable)时,过滤掉【iterable】中【function的结果为0】的内容:
>>> def odd(x): return x % 2 >>> temp = range(10) >>> show = filter (odd, temp) >>> list(show) [1, 3, 5, 7, 9]
2、filter() 与 lambda结合:
>>> list(filter(lambda x : x % 2, range(10))) [1, 3, 5, 7, 9]
(二)map() __映射
两个参数,(function, *iterable),直接代很多数计算(lambda进化版)
将可迭代序列的每一个数据作为函数的参数进行运算加工,直到可迭代序列的每一个元素都加工完毕,返回所有加工后的元素构成的新序列。
>>> list(map(lambda x : x * 2, range(10))) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
22 函数:递归是神马
普通程序员用迭代,高级程序员用递归!~
>>> def recursion(): return recursion() >>> recursion() Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> recursion() File "<pyshell#3>", line 2, in recursion return recursion() File "<pyshell#3>", line 2, in recursion return recursion() File "<pyshell#3>", line 2, in recursion return recursion() [Previous line repeated 990 more times] RecursionError: maximum recursion depth exceeded
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
recursion()
File "<pyshell#3>", line 2, in recursion
return recursion()
File "<pyshell#3>", line 2, in recursion
return recursion()
File "<pyshell#3>", line 2, in recursion
return recursion()
[Previous line repeated 990 more times]
RecursionError: maximum recursion depth exceeded无限循环,直接干掉python,可以设置一下递归的深度(100000层):
>>> import sys >>> sys.setrecursionlimit(100000)
不开玩笑了,进入正题。举个正常的例子:
(一)递归求阶乘:写一个求阶乘的函数:
正整数阶乘,如【5!】,就是【1*2*3*4*5】,为【120】。即【120是5的阶乘】
非递归方法
def factorial(n): result = n for i in range(1, n): result *= i return result
def factorial(n): result = 1 for i in range(1, n + 1): result *= i return result
【代码解读】标红为【result = n】或【result = 1】
__对于输入【n】,有【result = n × 1 × 2 × ... × (n-1)】
__对于输入【n】,有【result = 1 × 1 × 2 × ... × n】【利用前所学知识完善】:
def factorial(n): result = 1 for i in range(1, n + 1): result *= i return result
【笔记】复习【字符串格式化%d】
递归方法
def factorial(n): if n == 1: return 1 else: return n * factorial(n-1) number = int(input('请输入一个正整数:')) result = factorial(number) print("%d 的阶乘是: %d" % (number, result))
【原理】
递归很牛逼,但 只要会选择运用场景,就是天才编程师!
递归有风险,运用要谨慎!下节课讲 !~