#Python 装饰器-part1
最近刚开始学习python,想着弄个博客记录一下自己学习的过程,同时也是为了总结一下.本人之前没有学过什么编程语言,所以理解有些问题有点苦手,最近就碰到一个很头大的东西叫做装饰器(Decorator)
,在stackoverflow看到一篇很好的文章,解析的很详细,很适合我这样的初学者
.
阅读全文
Python的函数是对象
要理解装饰器,你首先需要理解在Python中,函数就是一个对象(object)
这很重要,让我们简单看个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| def shout(word="yes"): return word.capitalize()+"!" print shout() scream = shout print scream() del shout try: print shout() except NameError, e: print e print scream()
|
好了,记住这点,我们将会很快用到它.
Python函数另一个有趣的特性是,函数可以被定义在另一个函数里面.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def talk(): def whisper(word="yes"): return word.lower()+"..." print whisper() talk() try: print whisper() except NameError, e: print e Python's functions are objects
|
##函数引用
好了,到这里了,接下来是有意思的部分,我们刚才看到函数都是对象:
- can be assigned to a variable
- can be assigned to a variable
这意味着函数可以返回
另一个函数,让我们来看看☺
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| def getTalk(kind="shout"): def shout(word="yes"): return word.capitalize()+"!" def whisper(word="yes") : return word.lower()+"..."; if kind == "shout": return shout else: return whisper talk = getTalk() print talk print talk() print getTalk("whisper")()
|
但是,让我们想想,如果你可以返回一个函数,那么你也可以将函数作为参数传递
1 2 3 4 5 6 7 8
| def doSomethingBefore(func): print "I do something before then I call the function you gave me" print func() doSomethingBefore(scream)
|
好了,现在你已经了解要理解装饰器的每件事.
装饰器就是能让你在不改变被装饰函数本身下,在其之前或之后执行相关代码,即对某个函数的封装
下面我们手工创建一个装饰器的例子.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| def my_shiny_new_decorator(a_function_to_decorate): def the_wrapper_around_the_original_function(): print "Before the function runs" a_function_to_decorate() print "After the function runs" return the_wrapper_around_the_original_function def a_stand_alone_function(): print "I am a stand alone function, don't you dare modify me" a_stand_alone_function() a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function) a_stand_alone_function_decorated()
|
你肯定想你每次调用a_stand_alone_function
的时候,实际上调用的是a_stand_alone_function_decorated
,你只要重写a_stand_alone_function
就好了
1 2 3 4 5 6 7 8
| a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function) a_stand_alone_function()
|
##装饰器揭秘
我们用装饰器来演示前面的例子
1 2 3 4 5 6 7 8 9
| @my_shiny_new_decorator def another_stand_alone_function(): print "Leave me alone" another_stand_alone_function()
|
是不是很简单,实际上,装饰器只做了一件事
1
| another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
|
#装饰器进阶篇
##将参数传递给装饰器函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def a_decorator_passing_arguments(function_to_decorate): def a_wrapper_accepting_arguments(arg1, arg2): print "I got args! Look:", arg1, arg2 function_to_decorate(arg1, arg2) return a_wrapper_accepting_arguments @a_decorator_passing_arguments def print_full_name(first_name, last_name): print "My name is", first_name, last_name print_full_name("Peter", "Venkman")
|
##装饰类里面的方法method
在python中,类里面的方法和函数其实差不多是一样的,唯一的不同在于方法默认接收第一个参数为(self
)
让我们看看怎么装饰类里面的方法,只要记得第一个参数传为(self
)就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| def method_friendly_decorator(method_to_decorate): def wrapper(self, lie): lie = lie - 3 return method_to_decorate(self, lie) return wrapper class Lucy(object): def __init__(self): self.age = 32 @method_friendly_decorator def sayYourAge(self, lie): print "I am %s, what did you think?" % (self.age + lie) l = Lucy() l.sayYourAge(-3) 女人的年龄是秘密,哈哈哈
|
如果你想写一个接收任何参数的装饰器,我们可以使用*args
,**kwargs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| def a_decorator_passing_arbitrary_arguments(function_to_decorate): def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs): print "Do I have args?:" print args print kwargs function_to_decorate(*args, **kwargs) return a_wrapper_accepting_arbitrary_arguments @a_decorator_passing_arbitrary_arguments def function_with_no_argument(): print "Python is cool, no argument here." function_with_no_argument() @a_decorator_passing_arbitrary_arguments def function_with_arguments(a, b, c): print a, b, c function_with_arguments(1,2,3) @a_decorator_passing_arbitrary_arguments def function_with_named_arguments(a, b, c, platypus="Why not ?"): print "Do %s, %s and %s like platypus? %s" %\ (a, b, c, platypus) function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!") class Mary(object): def __init__(self): self.age = 31 @a_decorator_passing_arbitrary_arguments def sayYourAge(self, lie=-3): print "I am %s, what did you think ?" % (self.age + lie) m = Mary() m.sayYourAge()
|
待续(太特么长了)