python简单进阶,decorator

decorator

前提:everything in python is object even function,attributes,variables,params
看这篇之前请先看closure:python简单进阶,closure

两个有趣的例子
def inc(x):
    return x + 1


def dec(x):
    return x - 1

# 传进一个方法,和一个参数
# 返回这个方法
def operation(func, x):
    return func(x)


print(operation(inc, 1))

执行结果
2
# 可以看作 closure,只不过保存的参数是方法
# 其实就是closure,只不过保存的参数是方法
def make_pretty(func):
    def inner():
        print("I got decorated")
        func()

    return inner


def ordinary():
    print("I am ordinary")


pretty = make_pretty(ordinary)
pretty()
print(pretty.__closure__[0].cell_contents)

执行结果
I got decorated
I am ordinary
<function ordinary at 0x000000001BD854A8>
另外一种写法

add the @make_pretty to ordinary() is same to ordinary = make_pretty(ordinary)

def smart_divide(func):
    def inner(a, b):
        print("I am going to divide ", a, "and", b)
        if (b == 0):
            print("Whoops! cannot divide")
            return
        return func(a, b)

    return inner


@smart_divide
def divide(a, b):
    return a / b


print(divide(1, 2))
print(divide(1, 0))

看上面的形式可以总结出,能够给别的函数作为修饰器用的必须有如下的特性

  1. 作为修饰器的函数内部必须有一个inner()函数,且最终要返回inner
  2. 作为修饰器的函数内部inner()函数的参数个数必须和被修饰的函数接收的参数数目一直
  3. 修饰器函数必须接受一个参数,这个参数就是被修饰的方法

遵守如上写法,我们就能写一个修饰器

写一个能修饰任何方法的修饰器
def walk_for_all(func):
	def inner(*args, **kwargs):
		print "包装"
		print func(*args, **kwargs)
		print "包装"
	return inner
修饰器可以多个同时修饰
def father_protect(func):
    def inner(*args, **kwargs):
        print("F" * 30)
        func(*args, **kwargs)
        print("F" * 30)

    return inner


def mother_protect(func):
    def inner(*args, **kwargs):
        print("M" * 30)
        func(*args, **kwargs)
        print("M" * 30)

    return inner

@father_protect
@mother_protect
def child(msg):
    print(msg)

child("I am save")

执行结果
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
I am save
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

上面的例子都是我仔细写的,如果认真看完的话,应该会对decorator有比较好的理解。

猜你喜欢

转载自blog.csdn.net/qq_40666620/article/details/108063620