您的位置:首页 > 编程语言 > Python开发

从0开始学quantum之1:Python高级特性--装饰器

2013-07-31 19:24 357 查看
我想,由面向对象开发经验的人或多或少地都有接触过设计模式,大名鼎鼎的23中面向对象设计模式中,就有一种设计模式叫做装饰器模式,建议读者先自行理解一下。

所谓模式,是一种编程约定,是经过长期实践验证能够解决某类问题的代码框架。

模式存在的意义,首先它能解决一些通用性的问题(使得代码能适应需求变化,能轻松扩展)。其次是它能帮助程序员之间对代码的沟通,比如你告诉某个程序员说这段代码使用了XX模式,因为大家都知道这个模式是怎么实现的,所以对方也会很快地理解代码的实现。

装饰器模式是什么样的一种模式呢?

在Java或者C#语言里,一个类完A成特定单一的功能,当我们需求有变,需要扩展这个类A,运用装饰器模式,只要新增一个完成扩展功能的类B,然后再把原有功能的A的对象a注入到新类B中,这样新类B就具有了原来A的特性,同时又扩展了新功能。当然,这样做原有的类代码不更改,我们更希望调用者User使用方式也不更改,则新扩展的类B要有一套更原有类一样的接口I,使用者仍然是使用旧接口,就可调用扩展功能。
例如A类实现了登录功能,登录时匹配用户名密码是否与数据库保存的一致,B类则扩展了该登录功能,它扩展了验证码机制,防止攻击性密集型登录。


                                                           
    


因此,装饰器模式约定了

1、原有类与扩展类实现了同一个接口,例如上例中A和B都实现了登录接口,这样用户调用方式不变

2、扩展类可以注入旧类的对象(扩展一个类有2种方式,一种是继承旧类,一种是新类与旧类的对象进行组合),上例中把A类的对象a注入到B类中,B认证通过后调用a的登录接口,使用原有功能

3、扩展类可以被更新扩展的类注入,例如,当我们需要更多功能时,希望B也可以注入到新类中


言归正传,在Python语言里,装饰器特性已经不是模式约定那么简单了,它已经上升为一种语法,使用这样的语法就可以轻松实现装饰器模式。

在理解Python装饰器之前,Python的几个特性需要大家理解:

1、在Python里,任何东西都可以称为对象,类是对象,方法是对象,类的对象更是对象。

2、任何对象都可以当作方法来使用。类是方法,对象也是方法。

第1点大家就当作Python语言设计之初的一种理念好了,不必过分拘泥,第2点可能对初次接触Python的人来说,可能不好理解,下面用例子说明。

假如有一个类A,它重写了初始化函数__init__;重写了__call__方法,美其名曰实现了callable接口。

#coding:UTF-8
class A:
def __init__(self):
print 'init function'

def __call__(self):
print 'callable function'

#1、类可以当作方法使用
a = A() #其实就相当于调用了初始化函数__init__

#2、对象也可以作为方法使用
a() #其实就相当于调用了__call__方法因此,类可以当作方法来使用,对象也可以当作方法来使用,方法自然也是可以当作方法来使用了

进入正题,什么是Python装饰器呢?

Python定义了一种语法来实现装饰器的(decorator)模式:

@[decorator]

def [function]():

     do something

来看具体例子,这是一个最简单的Python装饰器语法的例子

def decorator(func):
def extendFunc():
print 'extend function'
func()
return extendFunc

@decorator
def function():
print 'this is ordinary function'

function()输出结果是:

extend function

this is ordinary function
它很符合我们之前对装饰器模式的约定:

1、在扩展功能extendFunc中有一个原有功能function的对象,在不修改function的情况下可以扩展新的功能。

2、对用户来说,调用方式不变,仍然是调用function,却实现了extendFunc的功能。

对Python装饰器语法的结论就是。

1、装饰器decorator是一个方法(也可以是一个类,或者一个对象,我们上文说过,类也是方法,对象也是方法)。

2、装饰器decorator必须有一个入参,接受被装饰的方法

3、装饰器decorator必须返回一个方法(也可以返回一个类,或者一个对象,因为类也是方法,对象也是方法),该方法扩展了一些function没有的功能,同时也具有function的功能(当然你也可以不用function的功能)

4、在function被decorator装饰后,首先function被当作入参传递到了decorator,然后decorator返回一个方法extendFunc来代替function

5、由于function被extendFunc代替,以后在调用function的地方,其实就是调用extendFunc


那么Python装饰器最基本的东西就在上面体现了,现在我们来看复杂一点的,高级一点的:

一、跨类装饰(用一个类中的方法装饰另一个类的方法)



1、用Deco.dec来装饰myFunc,实际上是把myFunc作为参数传递给了Deco.dec方法,并返回另一个方法extendFunc

    使得以后调用myFunc的地方会转调用extendFunc

2、由于装饰器语法的限制,用 Deco.dec装饰myFunc时必须用Deco类来引用(Deco.dec是通过类引用方法)

    因此注定了dec方法为类方法

3、必须返回一个方法,这是装饰器的约定,否则在调用myFunc的时候就不知道调什么方法了 

4、调用了myFunc的地方就转而调用extendFunc,所以在执行extendFunc的时候第一个实参是mycls

5、必须至少保留一个形参,因为你不知道调用者会传什么参数,所以我们这里可以使用可变参数*arg1和**arg2

6、被装饰的方法变成了普通方法,而装饰的方法则替代了被装饰的方法

二、用类来装饰方法






下面这个留给大家思考吧




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息