Python之面向对象:闭包和装饰器

一、闭包
1、
如果一个函数定义在另一个函数的作用域内,并且引用了外层函数的变量,则该函数称为闭包。
def outter():
name='python'
def inner():
print name
return inner
res=outter() 把inner的地址赋值给res
res() 相当于执行inner()函数。通过闭包,可以把局部变量在外部也可以使用
2、判断是否为闭包 res.func_closure
inner()函数就是一个闭包
3、通过闭包,可以把局部变量在外部也可以使用
 
二、装饰器 @开始的
装饰器属于闭包,把一个函数当做参数后返回一个替代版函数。
1、定义
在代码运行期间在不改变原函数定义的基础上,动态给该函数增加功能的方式,称之为装饰器(Decorator)
 
装饰器的具体定义:
1、把要装饰的方法作为输入参数;
2、在函数体内可以进行任意的操作(可以想象其中会有很多应用场景);
3、只要确保最后返回一个可执行的函数即可(可以是原来的输入参数函数,也可以是一个新函数)。
 
作用:装饰器是一个很著名的设计模式,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
总体来说,装饰器其实也是一个函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值给原来的标识符,并永久丧失对原始函数对象的访问。
(1)不带参数的装饰器
eg: ( @log装饰器)
#定义装饰器
def log(func):
def wrapper(*args,**kwargs):
print 'call %s'%func.__name__
return func(*args,**kwargs) return原函数,是为了返回保证原函数的返回值
return wrapper
 
解释:
因为有了(*args, **kw)这样的参数格式,这意味着装饰器能够接受拥有任何签名的函数作为自己的被装饰方法,同时能够用传递给它的参数对被装饰的方法进行调用。这样就能处理参数个数不同的函数了。
 
@log # 调用了log函数,并把now赋值给了log作为参数 @log = log(now)
def now():
now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
print 'current time is %s'%now
now() # now() == wraper()
如果now带有参数:now(2,3) @log =log(now) now(2,3)=log(now)(2,3) @log的返回值是wrapper 所以 now(2,3)=wrapper(2,3)
 
对于函数的又一次理解:
now() 相当于执行了now这个函数,ret=now() 相当于执行了now函数后,把返回值赋值给了ret
(2)带参数的装饰器
def deco(arg):
    def _deco(func):
        def __deco():
              print "before %s called [%s]." % (func.__name__, arg)
              func()
             print " after %s called [%s]." % (func.__name__, arg)
         return __deco
    return _deco
@deco("mymodule")
def myfunc():
    print " myfunc() called."
@deco("module2")
def myfunc2():
    print " myfunc2() called."
myfunc()
myfunc2()
 
2、python自带的三个装饰器
@classmethod 定义实例方法为类方法
@staticmethod 定义实例方法为静态方法
@porperty 属性(对类属性的操作)
 
3、优点和用途
抽离出大量函数中与函数功能本身无关的的雷同代码并继续重用。
使用装饰器可以将函数“修饰”为完全不同的行为,可以有效的将业务逻辑正交分解,如用于将权限与身份验证从业务中独立出来。
如果一个函数需要一个功能,如果这个功能可以被使用在很多函数上,或是函数并不是自己实现,那可以写个装饰器来实现这些功能。
概况的将,装饰器的作用就是为已经存在的对象添加一些额外的功能。
 
posted @ 2017-06-21 15:27  emily-qin  Views(379)  Comments(0Edit  收藏  举报