Python进阶: Decorator 装饰器你太美

python

函数 -> 装饰器

  函数的4个核心概念

  1.函数可以赋与变量

def func(message):

print('Got a message: {}'.format(message))

send_message = func

send_message('hello world')

#输出

#Got a message: hello world

  2.函数可以当作函数的参数

def get_message(message):

return 'Got a message: ' + message

def root_call(func, message):

print(func(message))

root_call(get_message, 'hello world')

输出

#Got a message: hello world

  3.函数里嵌套函数

def func(message):

def get_message(message):

print('Got a message: {}'.format(message))

return get_message(message)

func('hello world')

输出

#Got a message: hello world

  4.函数作为函数返回值(闭包)

def func_closure():

def get_message(message):

print('Got a message: {}'.format(message))

return get_message

send_message = func_closure()

send_message('hello world')

#输出

#Got a message: hello world

 

简单装饰器

  例

def my_decorator(func):

def wrapper():

print('wrapper of decorator')

func()

return wrapper

def greet():

print('hello world')

greet = my_decorator(greet)

greet()

  使用语法糖 @

def my_decorator(func):

def wrapper():

print('wrapper of decorator')

func()

return wrapper

@my_decorator

def greet():

print('hello world')

greet()

# 输出

# wrapper of decorator

# hello world

带有参数的装饰器

  直接在 wrapper函数中加上参数

def my_decorator(func):

def wrapper(message):

print('wrapper of decorator')

func(message)

return wrapper

@my_decorator #相当于 greet == wrapper(message)

def greet(message):

print(message)

greet('hello world')

# 输出

#wrapper of decorator

#hello world

  这个装饰器只能用在有一个参数的函数,如果想对任意参数的函数通用,可以这么写

def my_decorator(func):

def wrapper(*args, **kwargs):

print('wrapper of decorator')

func(*args, **kwargs)

return wrapper

带自定义参数的装饰器

  利用装饰器自定义参数这特性,实现重复执行装饰器内部函数

def repeat(num):

def my_decorator(func):

def wrapper(*args, **kwargs):

for i in range(num):

print('wrapper of decorator')

func(*args, **kwargs)

return wrapper

return my_decorator

@repeat(4)

def greet(message):

print(message)

greet('hello world')

# 输出:

# wrapper of decorator

# hello world

# wrapper of decorator

# hello world

# wrapper of decorator

# hello world

# wrapper of decorator

# hello world

原函数还是原函数?

greet.__name__

#输出

'wrapper'

help(greet)

# 输出

Help on function wrapper in module __main__:

wrapper(*args, **kwargs)

  可以看出,原函数的原信息会被wrapper取代

  如果不想其改变,那么可用内置装饰器@functools.wraps将原函数的元信息拷贝过去。

import functools

def my_decorator(func):

@functools.wraps(func)

def wrapper(*args, **kwargs):

print('wrapper of decorator')

func(*args, **kwargs)

return wrapper

@my_decorator

def greet(message):

print(message)

greet.__name__

# 输出

#'greet'

 类装饰器

  类装饰器主要依赖于 __call__()函数,每当调用类实例时,__call__()函数会被执行一次

class Count:

def __init__(self, func):

self.func = func

self.num_calls = 0

def __call__(self, *args, **kwargs):

self.num_calls += 1

print('num of calls is: {}'.format(self.num_calls))

return self.func(*args, **kwargs)

@Count

def example():

print("hello world")

example()

# 输出

# num of calls is: 1

# hello world

example()

# 输出

# num of calls is: 2

# hello world

装饰器的嵌套

@decorator1

@decorator2

@decorator3

def func():

...

#相当于 decorator1(decorator2(decorator3(func)))

import functools

def my_decorator1(func):

@functools.wraps(func)

def wrapper(*args, **kwargs):

print('execute decorator1')

func(*args, **kwargs)

return wrapper

def my_decorator2(func):

@functools.wraps(func)

def wrapper(*args, **kwargs):

print('execute decorator2')

func(*args, **kwargs)

return wrapper

@my_decorator1

@my_decorator2

def greet(message):

print(message)

greet('hello world')

# 输出

# execute decorator1

# execute decorator2

# hello world

装饰器的实例用法

  1)身份验证,不登录不允许操作

import functools

def authenticate(func):

@functools.wraps(func)

def wrapper(*args, **kwargs):

request = args[0]

if check_user_logged_in(request): # 如果用户处于登录状态

return func(*args, **kwargs) # 执行函数 post_comment()

else:

raise Exception('Authentication failed')

return wrapper

@authenticate

def post_comment(request, ...)

...

  2)日志记录 可测试函数的执行时间

import time

import functools

def log_execution_time(func):

def wrapper(*args, **kwargs):

start = time.perf_counter()

res = func(*args, **kwargs)

end = time.perf_counter()

print('{} took {} ms'.format(func.__name__, (end - start) * 1000))

return res

return wrapper

@log_execution_time

def calculate_similarity(items):

...

  3) 合法性检测

import functools

def validation_check(input):

@functools.wraps(func)

def wrapper(*args, **kwargs):

... # 检查输入是否合法

@validation_check

def neural_network_training(param1, param2, ...):

...

LRU cache. @lru_cache缓存装饰器

@lru_cache

def check(param1, param2, ...) # 检查用户设备类型,版本号等等

...

  4) try...excaption

class ServerDebugHelper:

@classmethod

def debug(cls):

def decorator(func):

@wraps(func)

def wrapper(*args, **kwargs):

try:

return func(*args, **kwargs)

except:

import traceback

print(traceback.format_exc())

return wrapper

return decorator

  

参考

  极客时间《Python核心技术与实战》专栏

以上是 Python进阶: Decorator 装饰器你太美 的全部内容, 来源链接: utcz.com/z/389284.html

回到顶部