python进阶之装饰器之2.定义一个可接受参数的装饰器、如何定义一个属性可由用户修改的装饰器、定义一个能接受可选参数的装饰器

2.1.定义一个接受参数的装饰器

前言:在理解上一篇文章的基础上理解定义一个接受参数的装饰器

思路:在装饰器函数的外层再定义一个接受参数的函数,让他返回装饰器函数,在装饰器函数中进行相关参数的进行操作

代码解析如下:

from functools import wrapsimport logging# 定义外层函数logged,使用return decorate返回装饰器函数def logged(level, name=None, message=None):    """    Add logging to a function. level is the logging    level, name is the logger name, and message is the    log message. If name and message aren‘t specified,    they default to the function‘s module and name.    """    # 定义一个装饰器,返回wrapper函数    def decorate(func):        # 对传入的参数进行相关操作        logname = name if name else func.__module__        print(logname)        log = logging.getLogger(logname)        print(log)        logmsg = message if message else func.__name__        print(logmsg)

@wraps(func)        # 定义wrapper函数,返回被装饰的func函数,即后面示例中的add函数或者spam函数        def wrapper(*args, **kwargs):            log.log(level, logmsg)            return func(*args, **kwargs)        return wrapper    return decorate

# Example use@logged(logging.DEBUG)def add(x, y):    return x + y

print(add(2,5))

输出:

__main__
<Logger __main__ (WARNING)>
add
7


@logged(logging.CRITICAL, ‘example‘)def spam():    print(‘Spam!‘)

print(spam())
输出:

example
<Logger example (WARNING)>
spam
Spam!

None              #若def函数后面追加一个return “hello”,则最后一个None改为hello

小结:

@decorator(x, y, z)
def func(a, b):
    pass

装饰器处理过程跟下面的调用是等效的;

def func(a, b):
    pass
func = decorator(x, y, z)(func)

2.2  如何定义一个属性可由用户修改的装饰器

前言:定义一个可以传参数的装饰器,若现在需要给以动态修改装饰器的属性,改若何定义呢?

思路:此处使用访问器函数(accessor function),然后nonlocal 来修改内部变量

代码解析如下:

from functools import wraps, partial
import logging

# Utility decorator to attach a function as an attribute of obj
def attach_wrapper(obj, func=None):
    if func is None:
        return partial(attach_wrapper, obj)
    setattr(obj, func.__name__, func)
    return func

def logged(level, name=None, message=None):
    ‘‘‘
    Add logging to a function. level is the logging
    level, name is the logger name, and message is the
    log message. If name and message aren‘t specified,
    they default to the function‘s module and name.
    ‘‘‘
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, logmsg)
            return func(*args, **kwargs)

        # Attach setter functions
        @attach_wrapper(wrapper)
        def set_level(newlevel):
            nonlocal level
            level = newlevel

        @attach_wrapper(wrapper)
        def set_message(newmsg):
            nonlocal logmsg
            logmsg = newmsg
        return wrapper
    return decorate

# Example use
@logged(logging.DEBUG)
def add(x, y):
    return x + y

@logged(logging.CRITICAL, ‘example‘)
def spam():
    print(‘Spam!‘)

# level级别默认设置为DEBUG
logging.basicConfig(level=logging.DEBUG)
print(add(2, 3))
# DEBUG:__main__:add
# 5

# Change the log message
add.set_message(‘Add called‘)
print(add(2, 3))
# DEBUG:__main__:Add called
# 5

# Change the log level
add.set_level(logging.WARNING)
print(add(2, 3))
# WARNING:__main__:Add called
# 5

若使用其他对于属性直接访问的方法,只能访问到顶层装饰器,例如:
@timethis
@logged(logging.DEBUG)
def countdown(n):
    while n > 0:
        n -= 1其中顶层装饰器函数为:@timethis,用直接访问属性的方法会失败,请记住这点

本小节的内容可以作为后续类装饰器的替代
 

原文地址:https://www.cnblogs.com/max520liuhu/p/9348077.html

时间: 2024-10-08 19:35:05

python进阶之装饰器之2.定义一个可接受参数的装饰器、如何定义一个属性可由用户修改的装饰器、定义一个能接受可选参数的装饰器的相关文章

《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记

看<Python cookbook>的时候,第9.5部分,"定义一个属性可由用户修改的装饰器",有个装饰器理解起来花了一些时间,做个笔记免得二刷这本书的时候忘了 完整代码:https://github.com/blackmatrix7/python-learning/blob/master/python_cookbook/chapter_9/section_5/attach_wrapper.py 书中的装饰器(书中称之为访问器函数) def attach_wrapper(o

Python进阶(六)----装饰器

Python进阶(六)----装饰器 一丶开放封闭原则 开放原则: ? 增加一些额外的新功能 封闭原则: ? 不改变源码.以及调用方式 二丶初识装饰器 装饰器: ? 也可称装饰器函数,诠释开放封闭原则,装饰器的本质是闭包 ###普通版装饰器 import time def timmer(x): # x 接收的原函数的内存地址 def inner(): start_time=time.time() x() # 执行 原函数 print(f'执行效率{time.time()-start_time}'

python+selenium自动化软件测试:装饰器之用例失败后截图

对于用例失败截图,很多小伙伴都希望用例执行失败的时候能自动截图,想法是很好的,实现起来并不是那么容易,这里小编分享下最近研究装饰器,打算用装饰器来实现自动截图. 一.函数作为形参1.函数的参数也可以是另外一个函数,也就是说传的参数不仅可以是常见的字符串.数字等,也可以是一个函数.2.定义aaa为一个加法函数,bbb为减法函数.3.calculate这个函数传三个参数,第一个参数是一个函数,另外两个参数是函数的两个参数. 二.万能装饰器1.由于不知道我们被调用的函数到底有几个参数,这时候就可以写一

[Python进阶]002.装饰器(1)

装饰器(1) 介绍 HelloWorld 需求 使用函数式编程 加入装饰器 解析 介绍 Python的装饰器叫Decorator,就是对一个模块做装饰. 作用: 为已存在的对象添加额外功能. 与Java中的注解相似,就是在方法前加@XXX来对这个方法做装饰. 与Java中的注解相当复杂不同,Python的装饰器相当简单. 函数式编程 面向切片编程 HelloWorld 需求 def fun(i): print i 这是一个简单的方法,现在我们要在执行这个方法前后在执行一些其他代码,比如计算运行时

Python进阶之装饰器

函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用.既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数传递或返回.同时,函数体中也可以再定义函数. 装饰器本质 可以通过编写一个纯函数的例子来还原装饰器所要做的事. def decorator(func):          def wrap():         print("Doing someting before executing fu

Python进阶之[非局部变量,闭包,装饰器]

阅读Tacotron2源码 之 Python进阶 Non-Local Variable with Nested Function Closure in Python Decorator 1. Non-Local Variable with Nested Function ????在Python中,除了全局变量(Global Variable)和局部变量(Local Variable)之外,还有一种变量叫Non-Local Variable. ????Non-Local Variable的存在来源

python装饰器之自己的理解,欢迎更正

pre.cjk { font-family: "Nimbus Mono L", monospace } h2.western { font-family: "Liberation Sans", sans-serif; font-size: 16pt } h2.cjk { font-family: "Noto Sans CJK SC Regular"; font-size: 16pt } h2.ctl { font-family: "Fr

Python进阶-----类的装饰器及应用

回顾什么是装饰器: 装饰器定义:本质就是函数(高阶函数),功能是为其他函数(对象)添加新功能 一.类的装饰器基本实现原理如下: 1 def deco(cls): 2 print('类的装饰器=========>') 3 print('='*20) 4 return cls 5 6 @deco #====> Foo = deco(Foo) 7 class Foo: 8 pass 二.上述的简单装饰器是没有参数的,现在我们加上参数 1 def cls_decorator(**kwargs): #支

react配置完装饰器之后运行yarn start时报错

配置完装饰器之后以运行yarn start就报错 There might be a problem with the project dependency tree.It is likely not a bug in Create React App, but something you need to fix locally. The react-scripts package provided by Create React App requires a dependency: "webpa