一、作用域
简单说就是一个变量能够起作用的区域
python中除了模块,类,函数之外,其他如if/elif/else/try/except/while/for 并不能改变作用域
1. 全局作用域
一个模块(.py文件内部)有效
a = "hello world" #全局变量
def func1():
a = "hello python" #局部变量
print("a in func1 =", a)
func1() #a in func1 = hello python
print("a in global =", a) #a in global = hello world
如果要在函数内部使用全局变量,需要用global关键字
a = "hello world" #全局变量
def func1():
global a #引用全局变量
a = "hello python" #对全局变量重新赋值
print("a in func1 =", a)
func1() #a in func1 = hello python
print("a in global =", a) #a in global = hello python
2. 局部作用域
只在某个区域内有效,如函数内部
def func1():
i=1 #i是局部变量
print(i) #i能在函数内部(局部)使用,不会报错
print(i) #在函数外使用i会报错: NameError: name 'i' is not defined
3. 嵌套作用域
嵌套一般是指一个函数嵌套另一个函数的情况,外层函数包含的作用域就是嵌套作用域
def outer():
a = "hello world" # 对于上层来说,是局部;对于下层来说,是嵌套
def inner():
a = "hello python"
print("a in inner =", a)
inner()
print("a in outer =", a)
outer()
'''
a in inner = hello python
a in outer = hello world
'''
4. 内置作用域
python系统内固定模块里定义好的变量,我们直接使用,如print()
二、高阶函数
一切皆对象,函数跟字符串,列表等普通数据类型一样都是对象,函数名也一样是一个变量名
1. 将函数名赋值给其他变量
def func1(): #定义一个函数
print('this is a function')
a=func1 #将函数名赋值给一个变量a
func1() #this is a function 调用函数func1
a() #this is a function 调用a,等于调用func1
print(id(func1)) #1422665511264
print(id(a)) #1422665511264 可以看出a和func1是一样的
2. 将函数名作为参数传递
def func1(): #定义一个函数
print('this is a function')
def func2(func): #定义一个函数,参数也是一个函数
func() #调用传递进来的函数名
func2(func1) #this is a function
3. 将函数名作为其他函数返回值
def outer(): #定义一个函数
def inner(): #在函数内部再定义一个函数
print('this is a function')
return inner #将内部函数名返回
result=outer() #调用外部函数,并用一个变量接收返回值,相当于result=inner
result() #this is a function 因为返回值是内部函数名,加上()即调用内部函数相当于inner()
三、闭包
在一个内部函数里边,对在外部作用域(嵌套作用域,但不能是全局作用域)的变量进行引用,那么这个内部函数就被认为是闭包
def outer():
x = 10
def inner():
print(x) #引用在外部作用域(嵌套作用域)的变量
return inner #返回内部函数名,便于在外面访问该内部函数
result=outer()
result() #10
四、装饰器
装饰器本质上是一个函数,该函数用来处理其他的函数,可以让其他函数在不需要修改代码的前提下,增加额外的功能,概括就是为已经存在的对象添加额外的功能,返回值是一个函数对象
对于如插入日志,性能测试,事务处理,缓存,权限校验等场景时,使用装饰器,可以抽离出与函数本身功能无关的相似代码并复用
例:有一个函数,需要在调用该函数时,执行函数原本功能并计算这个函数的执行时间
import time
def show_time(func): #定义计算函数执行时间的函数,将函数名作为参数传递
def inner(): #定义一个内部函数
begin_time = time.time() #将当前时间赋给变量
func() #执行函数
end_time = time.time() #将当前时间赋给变量
print("总计执行时间 =", end_time - begin_time)
return inner #返回内部函数
def func1(): #需要增加计算函数执行时间的原函数
print("执行测试用例")
time.sleep(1) #因为函数执行太快,所以等待1s
func1 = show_time(func1) #调用时间函数,并将返回值inner赋值给原函数名
func1() #调用原函数,但实际上是调用inner(),这样就让原函数不变的情况下,可以多执行时间的功能
'''
执行测试用例
总计执行时间 = 1.0077204704284668
'''
在上例中,func1是被装饰函数,show_time是装饰函数,也就是装饰器,但每次使用时都需要调用,赋值,比较麻烦,python中提供了一个语法糖使之更简单清晰
import time
def show_time(func):
def inner():
begin_time = time.time()
func()
end_time = time.time()
print("总计执行时间 =", end_time - begin_time)
return inner
@show_time #语法糖,在被装饰函数前加上,实现代码要在之前 相当于func1=show_time(func1)
def func1():
print("执行测试用例")
time.sleep(1)
func1()
带参数的装饰函数
def outer(func):
def inner(name):
func(name) # 需要保留被装饰函数原有的功能,所以通过传参的形式调用被装饰函数
print("这是新加的功能")
return inner
@outer
def func1(name):
print("测试姓名:", name)
func1("张三")
带参数的装饰器
def wrap(age):
def outer(func):
def inner(name):
func(name) # 需要保留被装饰函数原有的功能,所以通过传参的形式调用被装饰函数
print("这是新加的功能")
print("年龄是:", age)
return inner
return outer
# wraper(18) 相当于 outer,@wraper(18) 相当于 @outer, @outer 相当于 func1 = outer(func1) = inner
@wrap(18)
def func1(name):
print("测试订单:", name)
func1("张三")
'''
测试订单: 张三
这是新加的功能
年龄是: 18
'''