智一面的面试题提供python的测试题
使用地址:http://www.gtalent.cn/exam/interview?token=99ef9b1b81c34b4e0514325e9bd3be54
装饰器让你在一个函数的前后去执行代码。
# 一个装饰器函数,参数是一个函数
def a_new_decorator(a_func):
# 嵌套一个函数,用于在执行a_func之前执行其他操作
def wrapTheFunction():
# 执行a_func()之前,执行的操作
print("I am doing some boring work before executing a_func()")
# 执行a_func()函数
a_func()
# 执行a_func之后的一些操作
print("I am doing some boring work after executing a_func()")
# 返回一个函数地址,使得调用a_new_decorator时,转而调用内部的wrapTheFunction函数
return wrapTheFunction
# 测试示例,一个普通的函数,将作为装饰器参数
def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")
# 普通函数的正常执行状况
a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"
# 将一个函数赋值给一个变量,类似C语言中的函数指针操作,使得该变量使用()就可以调用其指代的函数
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()
# 执行这个装饰器函数,可以观察到结果如下
a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
上面演示的示例,正是python中装饰器所做的事。我们可以使用@
做到上述相同的结果。
# 装饰器函数
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
# 使用@使用一个装饰器
# 他将在调用a_function_requiring_decoration时,将该函数作为参数
# 传入作为装饰器函数的a_new_decorator中,产生类似
# a_new_decorator( a_function_requiring_decoration) 的调用效果
@a_new_decorator # 装饰器,
def a_function_requiring_decoration():
"""Hey you! Decorate me!"""
print("I am the function which needs some decoration to "
"remove my foul smell")
a_function_requiring_decoration()
#outputs: I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
#the @a_new_decorator is just a short way of saying:
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
接上述代码,我们运行print(a_function_requiring_decoration.__name__)
发现Ouput输出应该是"a_function_requiring_decoration",这里的函数被warpTheFunction替代了。
print(a_function_requiring_decoration.__name__)
#outputs: wrapTheFunction
- 1
- 2
它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
"""Hey yo! Decorate me!"""
print("I am the function which needs some decoration to "
"remove my foul smell")
print(a_function_requiring_decoration.__name__)
# Output: a_function_requiring_decoration
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
简单理解就是 @wraps可以保证装饰器修饰的函数的__name__的值保持不变。
而装饰器的作用是,在不改变原有功能代码的基础上,添加额外的功能,如用户验证等
@wraps(func)的作用是,不改变使用装饰器原有函数的结构(如__name__, doc)
示例:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return("Function is running")
can_run = True
print(func())
# Output: Function is running
can_run = False
print(func())
# Output: Function will not run
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
注意:@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
使用场景:
授权(Authorization)
装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权: