python装饰器

一、基本装饰器

#装饰函数
 2 def decorator(foo):
 3     def wrapper():
 4         print 'wrapper'
 5         return foo()
 6     return wrapper
 7 
 8 #自定义函数
 9 def abc():
10     print 'abc'
11 
12 #装饰abc
13 abc = decorator(abc)

调用abc()

输出:wrapper

           abc

#装饰函数
def decorator(foo):
  def wrapper():
    print ('wrapper')
    return foo()
  return wrapper

@decorator
def abc():
  print ('abc')

这种形式也能实现相同功能,加了语法糖@简化了形式,其过程就是执行@decorator之后将函数abc以参数形式进入decorator函数,执行函数体,函数体就是定义wrapper函数,所以这个时候不会有任何打印输出,只有再单独调用abc()的时候,才会都相应打印输出。

二、带参数的装饰器

这个参数指的是装饰器上的参数,也即@后面跟的函数的参数,带参数的装饰器外层需要再包一层函数

def decrator(*dargs, **dkargs):
    def wrapper(func):
        def _wrapper(*args, **kargs):
            print "decrator param:", dargs, dkargs
            print "function param:", args, kargs
            return func(*args, **kargs)
        return _wrapper
    return wrapper
 
@decrator(1, a=2)
def foo(x, y=0):
    print "foo", x, y
 
foo(3, y=4)
 
# 输出:
# decrator param: (1,) {'a': 2}
# function param: (3,) {'y': 4}
# foo 3 4

 bottle.py中自动转换参数类型的装饰器:

def validate(**vkargs):
    def decorator(func):
        def wrapper(**kargs):
            for key in vkargs:
                # 根据vkargs中的参数的类型对kargs的参数进行类型转换
                kargs[key] = vkargs[key](kargs[key])
            return func(**kargs)
        return wrapper
    return decorator
 
 
@validate(id=int, x=float, y=float)
def move(id, x, y):
    print "move %d (%0.2f, %0.2f)"%(id, x, y)
 
move(id="1", x="0.2", y="0.3")

 

三、@语法糖

import time
def time(func):
    print('gundan')
    print(func())

@time  
def xxx():
    print('Hello world!')
    return 10

输出:
gundan
Hello world!
10

如果多个@,自底向上调用开始,而且每一底层的@的输出作为上面@的参数带入进去,只有目标函数是最底部@的函数参数带入进去,如下:

def deco1(f):
    print ('decorate 1')
    print(f+1)

def deco2(f):
    print ('decorate 2')
    return f()+1

@deco1
@deco2
def foo():
    print ('hello')
    return 2

输出:
decorate 2
hello
decorate 1
4

可以看出,foo以函数参数形式进入deco2,而deco2的返回值作为参数进入deco1,两者不一样。

 

posted @ 2019-01-28 17:05  光彩照人  阅读(193)  评论(0)    收藏  举报