week3 day2函数高级用法

week3 day2函数高级用法

    • 一. 函数对象
    • 二. 函数嵌套
    • 2.1 函数的嵌套定义
    • 2.2 函数的嵌套调用
    • 三. 名称空间与作用域
    • 3.1 名称空间
    • 3.2 作用域
    • 四. 闭包函数
    • 五. 装饰器
    • 5.1 什么是装饰器?
    • 5.2 为何要用装饰器?
    • 5.3 怎么使用装饰器?
    • 5.4 语法糖
    • 5.5 叠加多个装饰器的运算规则

一. 函数对象

函数和变量有相通之处。变量的使用原则是先定义后引用,函数的使用原则是先定义后使用。变量名绑定了变量值对应的内存空间的内存地址。函数名绑定了函数体代码对应的内存空间的内存地址。因此,适用于变量名使用的场景也适用于函数名的使用场景。

  1. 赋值
变量
a=10
b=a
函数
def func():
	print(1)
f=func
print(f)----->func的内存地址
f()----->1
  1. 传参
变量
a=10
def func(x):
	...
func(a)
函数
def index():
	...
def func(m):
	...
func(index)
  1. 返回值
变量
a=10
def func():
	return a
函数
def index():
	...
def func():
	return index
res=func()
res()
  1. 在容器型数据结构中按照索引(key)取到
变量
a=10
list1=[a]
list1[0]
函数
def func():
	...
list1=[func]
list1[0]()

第四种函数对象的使用方法可以让我们之前写过的atm功能更加简洁:

def login():
	...
def register():
	...
def withdraw():
	...
def deposit():
	...
def transfer():
	...
func_info={
     
	'0':['退出',exit],
	'1':['登录',login],
	'2':['提现',register],
	'3':['存钱',withdraw],
	'4':['转帐',transfer]
}
while True:
	for key,value in func_info:
		print(key,value[0])
	choice=input('请输入您想执行的操作: ').strip()
	if choice in func_info():
		print('您正在执行 {} 操作'.format(func_info[choice][0]))
		func_info[choice][-1]()

二. 函数嵌套

2.1 函数的嵌套定义

def func():
	x=10
	def sub_func():
		print(1)
func()----->None

def func():
	x=10
	def sub_func():
		print(1)
	sub_func()
func()----->1

2.2 函数的嵌套调用

比较输入的多个值的最大值的函数

def max2(x,y):
	if x>y:
		return x
	else:
		return y
def max_many(*args):
	list1=list(args)
	res1=list1[0]
	if len(list1)>=2:
		for i in range(1,len(list1)):
			res1=max2(res1,list1[i])
	print(res1)

三. 名称空间与作用域

3.1 名称空间

名称空间namespaces

名称空间与作用域在定义阶段就确定了,而不是调用阶段

名称空间与作用域在定义阶段就确定了,而不是调用阶段

名称空间与作用域在定义阶段就确定了,而不是调用阶段

名称空间种类 定义 生命周期
内置名称空间 存放内置的名字 python解释器调用产生-python解释器关闭销毁
全局名称空间 存放的是顶级的名字 python文件运行产生-python文件停止运行销毁
局部名称空间 存放的是函数内的名字 调用函数时产生,调用结束销毁

三种名称空间没有任何相交关系,但为了方便理解,可以理解为三层结构。内置名称空间在在外层,内层包含若干个(和python文件个数相同)全局名称空间,全局名称空间内层包含若干个(和python文件中调用函数的个数相同)函数的局部名称空间。

即LEGB层次。local----->enclosing functions----->global----->built-in functions.

案例一:

def f1():
    x=555
    def f2():
        x=666
        print(x)
    f2()
x=444
f1()----->666

def f1():
    x=555
    def f2():
        print(x)
    f2()
x=444
f1()----->555

def f1():
    def f2():
        print(x)
    f2()
x=444
f1()----->444

案例二:

len=10
def func():
    len=2
    print(len)
func()----->2

len=10
def func():
    print(len)
func()----->10

def func():
    print(len)
func()----->len的内置名称空间的内存地址

案例三:名称空间与作用域只与定义阶段有关,与调用无关

x=111
def f1():
    print(x)
def f2():
    x=222
    f1()
f2()----->111

案例四:

x=111
def f1():
    print(x) # local variable 'x' referenced before assignment
    x=222
f1()

print(y) # name 'y' is not defined

3.2 作用域

  1. 全局作用域:内置名称空间+全局名称空间
    特点:全局存活,全局有效
x=10
def func():
	global x
	x=20
print('before func:',x)----->10
func()
print('after func:',x)----->20
  1. 局部作用域:局部名称空间
    特点:局部存活,局部有效
x=10
def index():
	x=20
	def func():
		nonlocal x
		x=10
	print('before func:',x)
	func()
	print('after func:',x)
index()----->20
		----->10

四. 闭包函数

闭:定义在函数内的函数

包:该函数引用了一个外层函数作用域的名字

def outter():
	x=10
	def wrapper():
		print(x)
	return wrapper

闭包函数其实就是另一种给函数传参的方式

为函数传参的两种方式:

  1. 利用实参为形参传值
def wrapper(x,y):
	print(x+y)
wrapper(1,2)----->3
  1. 闭包函数传值
def outter(x,y):
	def wrapper():
		print(x+y)
	return wrapper
f=outter(3,4)
f()----->7

五. 装饰器

5.1 什么是装饰器?

装饰器就是为被装饰对象添加新功能的工具。

5.2 为何要用装饰器?

开放封闭原则:
开放:对扩展新功能开放
封闭:对修改原代码封闭

原则:
1.不修改原函数的原代码
2.不改变原函数的调用方法

5.3 怎么使用装饰器?

无参装饰器模板

def outter(func):
	def wrapper(*args,**kwargs):
		res=func()
		return res
	return wrapper

有参装饰器模板

def chuancan(args):
	def outter(func):
		def wrapper(*args,**kwargs):
			res=func(*args,**kwargs)
			return res
		return wrapper
	return outter

5.4 语法糖

为了是使用装饰器的时候调用更加简便,引入了语法糖的概念。

import time
def outter(func):
	def wrapper(*args,**kwargs):
		start=time.time()
		res=func(*args,**kwargs)
		end=time.time()
		print(end-start)
		return res
	return wrapper

@outter
def index():
	time.sleep(1)
	print(123)
index()----->123  1.0028467

5.5 叠加多个装饰器的运算规则

def deco1(func1): # func1=wrapper2
	def wrapper1(*args,**kwargs):
		print(111)
		res1=func(*args,**kwargs)
		print('end1')
		return res1
	return wrapper1
def deco2(func2): # func2=wrapper3
	def wrapper2(*agrs,**kwargs):
		print(222)
		res2=func(*args,**kwargs)
		print('end2')
		return res2
	return wrapper2
def deco3(func3): # func3=index
	def wrapper3(*args,**kwargs):
		print(333)
		res3=func3(*args,**kwargs)
		print('end3')
		return res3
	return wrapper3

@deco1 # deco1(wrapper2)--->return --->wrapper1
@deco2 # deco2(wrapper3)--->return--->wrapper2
@deco3 # deco3(index)--->return--->wrapper3
def index():
	print('from index')

index()----->111
			 222
			 333
			 from index
			 end3
			 end2
			 end1

装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下
装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下
装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下

上面例子的具体原理图可以看下图:
week3 day2函数高级用法_第1张图片

你可能感兴趣的:(python学习,python)