Python decorator usage study notes

WBOY
Release: 2016-07-06 13:29:43
Original
1294 people have browsed it

In python, we often see the use of @func when defining functions. This is a decorator. A decorator is a function that takes a function as a parameter. It is often used to extend existing functions, that is, to add functions without changing the current function state.

def run():
  print "I'm run."
Copy after login

I have such a function, and I want to know when this function starts and ends. I should write it like this

def run():
  print time.ctime()
  print "I'm run."
  print time.ctime()
Copy after login

But if the function is not allowed to be modified, a decorator is needed

def count(func):
  def wrapper():
    print time.ctime()
    ret = func()
    print time.ctime()
    return ret
  return wrapper

@count
def run():
  print "I'm run."

      # print '2015-4-10'

Copy after login

eg:

def now():
  print '2015-4-10'
f = now
f()  
Copy after login

The function has a __name__ object that can be used as the function name defined by dir(func) func

now.__name__    # print 'now'
f.__name__     # print 'now'

print f       # print '<function now at 0x000000000213A908>'
print now      # print '<function now at 0x000000000213A908>'

Copy after login

We print the log through the decorator

def log(func):
  def wrapper(*args, **kwargs):
    print "call %s()" % func.__name__
    return func(*args, **kwargs)
  return wrapper

@log
def now():
  print '2015-4-10'

now()        # print 'call now()'

Copy after login

In fact, the decorator modified function is equivalent to, now = log(now), that is, the decorator function takes the modified function as a parameter and assigns it to the variable with the same name

functools.wraps function

When we use the decorator, the __name__ value of now changes

# 没有使用前
now.__name__    # print 'now'
# 使用后
now.__name__    # print 'wrapper'
Copy after login

When we use the decorator, now.__name__ uses the current now function, but after using it, the now function is actually log(now), that is, the return value of the log function is the wrapped wrapper. The solution is functools.wraps function.

Decoration closure, must call import functools
before use

def log(func):
  @functools.wraps(func)
  def wrapper(*args, **kwargs):
    ...
Copy after login

Decorator with parameters

If the decorator needs to pass in parameters, then you need to write a higher-order function that returns the decorator. Writing it is more complicated.

def login(level):
  def _deco(func):
    def wrapper(*args, **kwargs):
      if level >= 5:
        print '用户 VIP 等级 %d' % int(level-5)
      else:
        print '用户 屌丝 等级 %d' % abs(level-5)
      return func(*args, **kwargs)
    return wrapper
  return _deco

@login(5)
def user(username):
  print 'welcome, %s' % username

# 用户vip 等级0
# welcome, mink
user('mink')

Copy after login

The decorator with parameters is equal to func = decorator function (decorator parameter) (func)

Decorator class

Through the __call__ of the class, you can use the class like a function

class A(object):
  def __init__(self, func):
    self.func = func

  def __call__(self):
    return self.func() ** 2

@A
def foo():
  return 10

print foo()   # print 100
Copy after login

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template