Analyzing and mastering python ornaments (2)

After reading (1), you must already have a basic concept of decoration.In (2), I will do some research on the advanced usage of decorative ornaments.

1. Decorators with other parameters

Next to the example above, we hope that not everyone has permission to use this calculation function, only certain people can.

  def checktype(personname=None):
    def decorate(func):
        def wrapper(*args,**kwargs):
            count = 0
            if personname == 'ghy':
                str = []
                for n in args:
                    if not isinstance(n,(int,float)):
                        log= '{}Type of cannot be calculated'.format(n)
                        str.append(log)
                        count += 1
                if count == 0:
                    return func(*args,**kwargs)
                else:
                    print(str)
            else:
                print('{}, you are limited'.format(personname))
        return  wrapper
    return decorate

@checktype('test')
def calfunc(*numbers,sign=None):
    if sign is None:
        return 'please input a sign'
    if hasattr(case['+'], '__call__'):
        add=case['+']
        return print(add(*numbers))
#call
calfunc('a','b',sign='+') #Output test you are limited

2. Custom Decorator Properties

Sometimes we want to modify the parameters of an ornament by defining some properties for it
As shown in the previous example, we want to modify the personname value by attributes

from functools import wraps,partial
#Attach function properties to wrapper functions
#Using the partial function
#from functools import partial
#The partial function does this
#By fixing some parameters of a function (that is, setting the default value), a new function is returned, and it is easier to call the new function.
#The first parameter is the original function.
def add_attr(obj,func=None):
    if func is None:
        return partial(add_attr,obj)
    setattr(obj,func.__name__,func)
    return func

#Decorator
def checktype(personname=None):
    def decorate(func):
        #Keep some metadata of the original function such as function name without calfunc. u name_u output wrapper
        @wraps(func)
        def wrapper(*args,**kwargs):
            count = 0
            if personname == 'ghy':
                str = []
                for n in args:
                    if not isinstance(n,(int,float)):
                        log= '{}Type of cannot be calculated'.format(n)
                        str.append(log)
                        count += 1
                if count == 0:
                    return func(*args,**kwargs)
                else:
                    print(str)
            else:
                print('{}, you are limited'.format(personname))

        @add_attr(wrapper) #Equivalent to add_attr (wrapper) ()=>add_attr (wrapper, sef_modifypersonname)
        def sef_modifypersonname(newname):
            nonlocal personname  # Without this, the next sentence creates another personal in the current scope
            personname = newname

        return  wrapper
    return decorate
@checktype('test')
def calfunc(*numbers,sign=None):
    if sign is None:
        return 'please input a sign'
    if hasattr(case['+'], '__call__'):
        add=case['+']
        return print(add(*numbers))

calfunc(1,2,sign='+') #Output test you are limited
calfunc.sef_modifypersonname('ghy')
calfunc(1,2,sign='+') #Output 3

#Decorator unpacking, call u wrapped_u do not enter decorator wrapper function
calfunc.sef_modifypersonname('test')
calfunc.__wrapped__(1,2,sign='+') #Output 3

One of the more important and slightly incomprehensible points above is @add_attr(wrapper), but you just need to understand

Decorator is called when code is interpreted

That is to say the code at our decorator, we can automatically default it to

sef_modifypersonname=add_attr(wrapper)(sef_modifypersonname)

Another is that the @wraps(func) comment is clearly written, preserving the metadata of the original function.

Posted on Wed, 06 May 2020 12:38:52 -0400 by jwang