函数补(递归,闭包,嵌套)

变量作用域

  • Python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的
  • Python作用于一共有四种
    • L(local)局部作用域,在函数,类等内部可见
    • E(enclosing)闭包函数外的函数中
    • G(global)全局作用域,在整个程序运行环境中都可见
    • B(built-in)内建作用域
  • 以L—E—G—B的规则查找
  • 全局作用域好处:使用方便,可以在任何地方使用
  • 坏处:有可能使用者会破坏原有的值
  • 函数内部可以访问全局变量,但不能直接修改全局变量,除非提前声明(global)

嵌套函数

  • 在一个函数中定义了另外一个函数
x = int(2.9)  #内建作用域
g_count = 0  #全局作用域
def outer():
	o_count = 1  #闭包函数外的函数中
	def inner():
		i_count = 2  #局部作用域
  • Python中只有模块(module),类(class)以及函数(def、lambda)才会引进新的作用域
a = 1000  #全局变量
def func():
	a = 500  #局部变量,相当于定义了新的变量,只是和全局变量名字相同而已
	a += 100
	print(a)
func()
print(a)  #600
		   1000
  • 外部不能访问内部变量,函数内部能访问外部变量,变量不声明函数里面改不了外部变量

global

  • 在编写程序的时候,如果想为一个在函数外的变量重新赋值,并且这个变量会作用于许多函数中时,此时用global语句就能修改全局变量
  • 案例1:
a = 1000
def func():
	a = 200
	print(a)
func()
print(a)  #200
		   1000
  • 案例2:
a = 1000
def func():
	global a  #声明变量
	a = 200  #此后a已修改为200
	print(a)
func()
print(a)  #200
		   200
  • 如果通过方法去更改全局变量,不用global
a = []
def app():
	a.append(22)
print(a)
app()
print(a)
#[]
 [22]

nonlocal

  • nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
  • 案例1:
a = 1000
def func1():
    a = 100
    def func2():
        a = 300
        print(a)
    func2()
    print(a)
func1()  #300
		  100
  • 案例2:
a = 1000
def func1():
    a = 100
    def func2():
        nonlocal a  
        a = 300
        print(a)
    func2()
    print(a)
func1()  #300
		  300

闭包Closure

  • 函数里面嵌套一个函数,这个函数用到外面函数中的变量,这些统称闭包
  • 函数里面再定义一个函数,并且外层函数返回了内层函数体
  • 里层函数用到了外层函数的变量
  • 闭包是概念,不是某种函数类型,和递归的概念类似,就是一种特殊的函数调用
  • 闭包可以得到外层函数的局部变量 ,是函数内部和函数外部沟通的桥梁
  • 可以实现封装,面向对象的特点之一就是封装
def func1(a):
    def func2(b):
        print(b * 2)
        return 2222
    print(a * 2)
    return func2
a = func1(20)
print(a)
print(a(30))
#40
 <function func1.<locals>.func2 at 0x7f55672d4620>
 60
 2222	

递归函数

  • 递归中可以函数自身调用自身,但是使用时类似于条件循环一样,要有递归的终止条件
  • 使用递归时,常常可以让代码更加简洁,但会占用比较多的内存,当递归次数比较多时,性能就会降低,因此不建议多使用递归
  • 注:
    • 递归函数要有参数
    • 要定义递归的边界
def factorial(n):
	if n == 1:
		return 1
	else:
		return n * factorial(n-1)   #n*(n-1)*n(n-2)......
res = factorial(3)
print(res)		#6
#公式:n!或者n*(n-1)*(n-2)......
def factorial(n):
	if n == 1:	#当n为1时,return 1,函数终止
		return 1		#函数中有return,就不会再执行return后面的代码
	return n * factorial(n-1)   #n*(n-1)*n(n-2)......
res = factorial(3)
print(res)		#6

汉诺塔

def hannt(n,x,y,z):
    if n == 1:
        print(x,'--->',z)
    else:
        hannt(n-1,x,z,y)    # x ---> y,所以这里将 y,z 位置互换
        print(x,'--->',z)
        hannt(n-1,y,x,z)    # y ---> z,所以这里将 x,y 位置互换

回调函数(所谓的)

  • 函数作为参数进行处理
def add(a,b):
    return a + b

def test(a,b,func):	
    print(a,b,func)
    
    return func(a,b) if callable(func) else print('{}不是函数'.format(func))

print(test(100,300,add))	#传入的第三个参数add对应上面的函数
test(200,200,111)
#100 300 <function add at 0x7f611ea06e18>
 400
 200 200 111
 111不是函数

匿名函数lambda

  • lambda 函数不能包含命令
  • 包含的表达式不能超过一个
  • 它们可以用在需要封装特殊的、非重要代码上,避免代码充斥着大量单行函数
  • lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边的为表达式,其实lambda返回值是一个函数的地址,也就是函数对象
c = lambda a,b:a + b
print(c)
print(c(1,2))
#<function <lambda> at 0x7fd9e4440e18>
 3 <class 'function'>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值