十三.函数嵌套,名称空间与作用域,闭包函数

一.函数嵌套

1.函数嵌套定义:在一个函数内又定义了另外一个函数

示例1:

def f1():
	def f2():
		print('from f2')
	f2()
	x=111111
	return x
f1()
res=f1()
print(res)  

示例2:

def f1():
	def f2():
		print('from f2')
	return f2
res = f1()
print(res)  # <function f1.<locals>.f2 at 0x000001F21FEED550>
res()  # from f2

示例3:

import math
def circle(radius,mode):
	def perimeter(radius):
		return 2 * math.pi * radius
	def area(radius):
		return math.pi * (radius ** 2)
	if mode == 1:
		return perimeter(radius)
	elif mode == 2:
		return area(radius)

print(circle(18,1))
print(circle(18,2))

2.函数嵌套调用:

在调用一个函数的过程中又调用了其他函数

def max2(x,y):
	if x > y :
		return x
	else:
		return y

def max4(a,b,c,d):
	res1=max2(a,b)
	res2=max2(res1,c)
	res3=max2(res2,d)
	return res3
print(max4(1,2,3,4))

二.名称空间与作用域

(1)名称空间就是存放名字的地方

1.内置名称空间:

存放的是python解释器自带的名字,如len,print,input
生命周期:解释器启动则创建,解释器关闭就销毁

2.全局名称空间:

内置以及函数内的名字之外的都存放与全局名称空间中
生命周期:运行顶级代码/主流水线创建,顶级代码/主流水线结束则销毁

x = 10
y = 12
## foo=内存地址
def foo(): #foo本身也是全局的
	z = 11
	#f1=内存地址
	def f1():
		pass

if True:
	aaa = 33

3.局部名称空间:函数内的名字

生命周期:函数调用时则创建,函数调用完毕则立即销毁

def f1(x,y):
	z=3
	def f2():
		m=444
		n=555
		f2()
f1(1,2)

(2)名称空间名字的查找顺序:基于当前所在的位置向上查找

局部–>外层套的局部–>外层套的局部–>…–>全局–>内置

示范1:站在全局进行查找

input = 33
def f1():
	input=444

f1()

print(input)

示范2:站在局部进行查找

def f1():
	input=4444
	print(input)
input=333
f1()

示范3:

def f1():
	#input = 444
	print(input)
def f2():
	#input = 555
	print(input)

input = 333

f1() # 333
f2() # 333

示范4:

def f1():
	input = 444
	def inner():
		input = 555
		print(input)
	inner()
input = 333
f1() # 555

注意:

名称空间的’嵌套关系’是函数定义阶段,也就是检测语法的时候就确定的,与调用无关

x = 111

def f1():
	print(x)

def f2():
	x = 222
	f1()

f2()

示范5:

def f3():
	print(x)
	x = 3333
x = 222
f3()  # 报错 local variable 'x' referenced before assignment

3.作用域

全局作用域:内置名称空间,全局名称空间
全局存活,全局有效
局部作用域:局部名称空间
临时存活,局部有效

4.函数的参数传递是值拷贝

示范1:对全局定义的不可变类型,不可以在函数内直接修改

x = 10
def func(a):# a = 10的内存地址
	a = 123

func(x) # x = 10的内存地址

print(x) # 10

示范2:对全局定义的可变类型,可以在函数内直接修改

x = []
def func(a): # a=[]的内存地址
	a.append(1111)
	a = 123
func(x)  # x=列表的内存地址
print(x) #[1111]

示范3:在函数内修改全局的不可变类型(global)

global:

如果函数外部有这个全局变量,在函数内部使用global关键字,可以修改全局变量,
如果函数外部没有这个全局变量,在函数内部使用global,可以定义全局变量
x = 10
l = []

def func():
	global x
	x = 666
	l.append(11111)
func()
print(x)  # 666
print(l)  # [11111]

示范4:nonlocal(了解)

nonlocal:关键字,专门用来修改当前作用域上一级的局部变量,遵循LEGB原则

x = 10
def f1():
	x = 11
	def f2():
		#global x
		nonlocal x
		x = 666
	f2()
	print('f1内的x===>',x) # f1内的x===> 666

f1()
print(x) # 10

三.闭包函数

内函数使用了外函数的局部变量,外函数将内函数返回出来的过程,叫做闭包,
里面的函数叫做闭包函数
特点:内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,
延长该变量的生命周期	

闭包函数

闭包函数=函数对象+函数嵌套定义+名称空间与作用域
闭: 指的是定义函数内的函数
包:指的是内函数引用了外函数的变量
def outter():
	x = 111
	def inner():
		print(x)

	return inner  # 这里不能加括号

f = outter()
print(f)

def f3():
	x = 222
	f()
f3()

为函数体代码传参的方式有两种

方式1:直接通过参数的方式传入

def func(x):
	print(x)
	
func(1)
func(2)
func(3)

方式二:使用闭包函数

def outter(x):
	# x = 2

	def func():
		print(x)
	return func

f1=outter(1)
f2=outter(2)
f3=outter(3)

f1()
f2()
f3()

猜你喜欢

转载自blog.csdn.net/yikenaoguazi/article/details/106803651