程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python Advanced Series (5)

編輯:Python

Catalog

Decorator

Use scenarios

to grant authorization (Authorization)

journal (Logging)

Parameter decorator

Embed decorators in functions

Decorator class


Decorator

Use scenarios

Now let's take a look at where the decorator is particularly dazzling , And using it can make some things easier to manage .

to grant authorization (Authorization)

A decorator can help to check if someone is authorized to use a web The endpoint of the application (endpoint). They are

Used in Flask and Django web In the frame . Here is an example of using decorator Based Authorization :

from functools import wraps
def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            authenticate()
        return f(*args, **kwargs)
return decorated

journal (Logging)

Log is another highlight of decorator application . This is an example :

from functools import wraps
def logit(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging
@logit
def addition_func(x):
    """Do some math."""
    return x + x
result = addition_func(4)
# Output: addition_func was called

I'm sure you're already thinking about one of the other clever uses of decorators .

Parameter decorator

Think about this problem , Don't @wraps Isn't it also a decorator ? however , It takes a parameter , Just like any ordinary function can do . that , Why don't we do the same ?

This is because , When you use @my_decorator Grammatical time , You are applying a wrapped function with a single function as an argument . remember ,Python Everything in the is an object , And this includes functions ! Remember these , We can write a function that can return a wrapped function .

Embed decorators in functions

Let's go back to the example of logs , And create a wrap function , Allows us to specify a log file for output .

from functools import wraps
def logit(logfile='out.log'):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # open logfile, And write content
            with open(logfile, 'a') as opened_file:
                # Now type the log to the specified logfile
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)
        return wrapped_function
    return logging_decorator
@logit()
def myfunc1():
    pass
myfunc1()
# Output: myfunc1 was called
# Now one is called out.log Your file appears , The content is the string above
@logit(logfile='func2.log')
def myfunc2():
    pass
myfunc2()
# Output: myfunc2 was called
# Now one is called func2.log Your file appears , The content is the string above 

Decorator class

Now we have... That can be used in a formal environment logit Decorator , But when some parts of our application are still fragile , Exceptions may be something that needs more urgent attention . For example, sometimes you just want to log to a file . And sometimes you want to send a question that gets your attention to email, Also keep logs , Keep a record . This is a scenario using inheritance , But so far we've only seen the functions used to build the decorator .

Fortunately, , Class can also be used to build decorators . So now we're using a class instead of a function , To rebuild logit.

from functools import wraps
class logit(object):
    def __init__(self, logfile='out.log'):
        self.logfile = logfile
    def __call__(self, func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # open logfile And write
            with open(self.logfile, 'a') as opened_file:
                # Now print the log to the specified file
                opened_file.write(log_string + '\n')
            # Now? , Send a notification
            self.notify()
            return func(*args, **kwargs)
        return wrapped_function
    def notify(self):
        # logit Just log , Nothing else
        pass

This implementation has an additional advantage , It's cleaner than nesting functions , And wrapping a function still uses the same syntax as before :

@logit()
def myfunc1():
    pass

Now? , We give logit Create subclass , To add email The function of ( although email This topic will not start here ).

class email_logit(logit):
    One logit Implementation version of , Can be sent on function call email To the administrator


    def __init__(self, email='[email protected]', *args, **kwargs)
        self.email = email
        super(logit, self).__init__(*args, **kwargs)
    def notify(self):
        # Send a email To self.email
        # It's not going to happen here
        pass

From now on ,@email_logit Will and @logit Same effect , But based on the log , An additional email will be sent to the administrator .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved