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有比较好的理解。

带参数和不带参数的区别


CLASS_DICT = {}

# 带参数, 实际上就相当于执行了一遍函数, 返回的是修饰器本身
def class_decorator(_type):
	def _real_decorator(_class):
		def __call(*args, **kwargs):
			return _class(*args, **kwargs)
		CLASS_DICT[_type] = A
		return __call
	return _real_decorator

# 不带参数, 就是第一层拿到的是class, 第二层拿到的是执行时传进来的参数
# 和函数的修饰器一样的, 第一层就是函数本身, 第二层是执行时传进来的参数
def class_decorator_2(_class):
	def __call(*args, **kwargs):
		return _class(*args, **kwargs)
	return __call

# @class_decorator('A')
@class_decorator_2
class A(object):
	
	def __init__(self):
		self.a = 1
		

a = A()
print a.a

核心:

带参数时相当于执行了一遍函数, 返回的是修饰器
修饰器的参数, 第一层是类 | 函数本身, 第二层是call() 时传进来的参数, 类就是实例化时的参数, 函数就是执行时的参数

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值