Python基础(伍) python装饰器使用

这是在Python学习小组上介绍的内容,现学现卖、多练习是好的学习方式。


第一步:最简单的函数,准备附加额外功能
# -*- coding:gbk -*-
'''示例1: 最简单的函数,表示调用了两次'''

def myfunc():
    print("myfunc() called.")

myfunc()
myfunc()



第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
# -*- coding:gbk -*-
'''示例2: 替换函数(装饰)
装饰函数的参数是被装饰的函数对象,返回原函数对象
装饰的实质语句: myfunc = deco(myfunc)'''

def deco(func):
    print("before myfunc() called.")
    func()
    print("  after myfunc() called.")
    return func

def myfunc():
    print(" myfunc() called.")

myfunc = deco(myfunc)

myfunc()
myfunc()


第三步:使用语法糖@来装饰函数
# -*- coding:gbk -*-
'''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)”
但发现新函数只在第一次被调用,且原函数多调用了一次'''

def deco(func):
    print("before myfunc() called.")
    func()
    print("  after myfunc() called.")
    return func

@deco
def myfunc():
    print(" myfunc() called.")

myfunc()
myfunc()



第四步:使用内嵌包装函数来确保每次新函数都被调用
# -*- coding:gbk -*-
'''示例4: 使用内嵌包装函数来确保每次新函数都被调用,
内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''

def deco(func):
    def _deco():
        print("before myfunc() called.")
        func()
        print("  after myfunc() called.")
        # 不需要返回func,实际上应返回原函数的返回值
    return _deco

@deco
def myfunc():
    print(" myfunc() called.")
    return 'ok'

myfunc()
myfunc()


第五步:对带参数的函数进行装饰
# -*- coding:gbk -*-
'''示例5: 对带参数的函数进行装饰,
内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象'''

def deco(func):
    def _deco(a, b):
        print("before myfunc() called.")
        ret = func(a, b)
        print("  after myfunc() called. result: %s" % ret)
        return ret
    return _deco

@deco
def myfunc(a, b):
    print(" myfunc(%s,%s) called." % (a, b))
    return a + b

myfunc(1, 2)
myfunc(3, 4)



第六步:对参数数量不确定的函数进行装饰
# -*- coding:gbk -*-
'''示例6: 对参数数量不确定的函数进行装饰,
参数用(*args, **kwargs),自动适应变参和命名参数'''

def deco(func):
    def _deco(*args, **kwargs):
        print("before %s called." % func.__name__)
        ret = func(*args, **kwargs)
        print("  after %s called. result: %s" % (func.__name__, ret))
        return ret
    return _deco

@deco
def myfunc(a, b):
    print(" myfunc(%s,%s) called." % (a, b))
    return a+b

@deco
def myfunc2(a, b, c):
    print(" myfunc2(%s,%s,%s) called." % (a, b, c))
    return a+b+c

myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)


第七步:让装饰器带参数
# -*- coding:gbk -*-
'''示例7: 在示例4的基础上,让装饰器带参数,
和上一示例相比在外层多了一层包装。
装饰函数名实际上应更有意义些'''

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()


第八步:让装饰器带 类 参数

# -*- coding:gbk -*-
'''示例8: 装饰器带类参数'''

class locker:
    def __init__(self):
        print("locker.__init__() should be not called.")

    @staticmethod
    def acquire():
        print("locker.acquire() called.(这是静态方法)")

    @staticmethod
    def release():
        print("  locker.release() called.(不需要对象实例)")

def deco(cls):
    '''cls 必须实现acquire和release静态方法'''
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, cls))
            cls.acquire()
            try:
                return func()
            finally:
                cls.release()
        return __deco
    return _deco

@deco(locker)
def myfunc():
    print(" myfunc() called.")

myfunc()
myfunc()


第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器

# -*- coding:gbk -*-
'''mylocker.py: 公共类 for 示例9.py'''

class mylocker:
    def __init__(self):
        print("mylocker.__init__() called.")

    @staticmethod
    def acquire():
        print("mylocker.acquire() called.")

    @staticmethod
    def unlock():
        print("  mylocker.unlock() called.")

class lockerex(mylocker):
    @staticmethod
    def acquire():
        print("lockerex.acquire() called.")

    @staticmethod
    def unlock():
        print("  lockerex.unlock() called.")

def lockhelper(cls):
    '''cls 必须实现acquire和release静态方法'''
    def _deco(func):
        def __deco(*args, **kwargs):
            print("before %s called." % func.__name__)
            cls.acquire()
            try:
                return func(*args, **kwargs)
            finally:
                cls.unlock()
        return __deco
    return _deco

# -*- coding:gbk -*-
'''示例9: 装饰器带类参数,并分拆公共类到其他py文件中
同时演示了对一个函数应用多个装饰器'''

from mylocker import *

class example:
    @lockhelper(mylocker)
    def myfunc(self):
        print(" myfunc() called.")

    @lockhelper(mylocker)
    @lockhelper(lockerex)
    def myfunc2(self, a, b):
        print(" myfunc2() called.")
        return a + b

if __name__=="__main__":
    a = example()
    a.myfunc()
    print(a.myfunc())
    print(a.myfunc2(1, 2))
    print(a.myfunc2(3, 4))



九,让装饰器带参与同时函数也带参数
#
def login(url,data):#装饰器两个参数
    def war(func):
        def  ck(a): #函数一个参数
            a='555' #这里将函数的参数值给改了。
            print "Start"
            ret = func(a)
            print ret
            print "End"
            return ret
        return ck
    return war


#函数
@login('123','345')
def to_int(str):
  print(str)

print to_int('777') #调用函数

#输出
D:\Python27\python.exe D:/HttpRunnerManager-master/HttpRunnerManager-master/test.py
Start
555
End
555


下面是参考资料,当初有不少地方没看明白,真正练习后才明白些:

1. Python装饰器学习 http://blog.csdn.net/thy38/article/details/4471421

2. Python装饰器与面向切面编程 http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html

3. Python装饰器的理解 http://apps.hi.baidu.com/share/detail/17572338

Python 基础 装饰器,python基础装饰器

   
明日把学过的装饰器的文化展开追思一下,说起装饰器,第二反应正是其一东西呢正是用来装逼的,为什么那样说吧,是应为未有这几个东西还能干活,抢先二分之一干活都是足以做的,不管怎样照旧把学过的装逼器梳理一下吧。

    1、装饰器是个什么样鬼?

       
装饰的意趣呢,便是修饰,装点的意味能够给别的函数添加新的效果,器呢正是函数的情致,so
装饰器便是为其他函数添加新的效应的函数。

    二、作为一个装饰器,他、它有哪些的规则吧?  

        一.不改动被点缀函数的源代码(开放封闭原则)

        2.为棉被服装饰函数添加新功效后,不修改被修饰函数的调用格局

    3、如何兑现七个装饰器呢?

       
要促成1个能够使用的装饰器就需求满足:装饰器=高阶函数+函数嵌套+闭包

    ④、高阶函数

       
上节牵线完了什么是高阶函数,只要满足:一.函数得以承受函数名当参数举办传递
2.函数的再次来到值能够回去三个函数名 
只要能够满意下边包车型大巴其它一条就认为构成的这些函数是高阶函数

        高阶函数的事例:

def foo():
    print('我的函数名作为参数传给高阶函数')
def gao_jie1(func):
    print('我就是高阶函数1,我接收的参数名是%s' %func)
    func()

def gao_jie2(func):
    print('我就是高阶函数2,我的返回值是%s' %func)
    return func

gao_jie1(foo)
gao_jie2(foo)
输出的结果是:
我就是高阶函数1,我接收的参数名是<function foo at 0x006896A8>
我的函数名作为参数传给高阶函数
我就是高阶函数2,我的返回值是<function foo at 0x006896A8>

#高阶函数应用1:把函数当做参数传给高阶函数
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print('函数%s 运行时间是%s' %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式

把函数当做参数传给高阶函数

#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    return func
    stop_time=time.time()
    print('函数%s 运行时间是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能

函数返回值是函数名

伍、函数嵌套(正是函数中还有定义函数)

def father(name):
    print('from father %s' %name)
    def son():
        print('from son')
        def grandson():
            print('from grandson')
        grandson()
    son()

father('还是牛')

6、闭包:(在3个功效域中放入的概念变量,仿佛打了一个包)

#闭包的概念:闭就是封装的意思,就是把变量分装起来;包:就是层的意思,与之前作用域意思是一样的。
#grandson中的变量有name(形式参数);son中的变量有grandson(函数名也是变量);father中的变量有:name(形式参数) son
def father(name):
    print('from the father %s' %(name))
    def son():
        print('from the son')
        def grandson():
            print('from the grandson %s'%(name))
        grandson()
    son()

father('SB')

七、装饰器的主旨框架

def timmer(func):
    def wrapper():
        print(func)
        func()
    return wrapper

def boo():
    print('你就是个傻逼!')


res = timmer(boo) # 返回的是wrapper的内存地址 <function timmer.<locals>.wrapper at 0x02129420>
#print(res)
res() #是在执行wrapper 函数

八、装饰器的二种方式:

先是种 无参数的装饰器

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]

current_user={'username':None,'login':False}

def auth_deco(func):
    def wrapper(*args,**kwargs):
        if current_user['username'] and current_user['login']:
            res=func(*args,**kwargs)
            return res
        username=input('用户名: ').strip()
        passwd=input('密码: ').strip()

        for index,user_dic in enumerate(user_list):
            if username == user_dic['name'] and passwd == user_dic['passwd']:
                current_user['username']=username

                current_user['login']=True
                res=func(*args,**kwargs)
                return res
                break
        else:
            print('用户名或者密码错误,重新登录')

    return wrapper

@auth_deco
def index():
    print('欢迎来到主页面')

@auth_deco
def home():
    print('这里是你家')

def shopping_car():
    print('查看购物车啊亲')

def order():
    print('查看订单啊亲')

print(user_list)
# index()
print(user_list)
home()

其次种 含有参数的装饰器

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]

current_user={'username':None,'login':False}
def auth(auth_type='file'):
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if auth_type == 'file':
                if current_user['username'] and current_user['login']:
                    res=func(*args,**kwargs)
                    return res
                username=input('用户名: ').strip()
                passwd=input('密码: ').strip()

                for index,user_dic in enumerate(user_list):
                    if username == user_dic['name'] and passwd == user_dic['passwd']:
                        current_user['username']=username
                        current_user['login']=True
                        res=func(*args,**kwargs)
                        return res
                        break
                else:
                    print('用户名或者密码错误,重新登录')
            elif auth_type == 'ldap':
                print('巴拉巴拉小魔仙')
                res=func(*args,**kwargs)
                return res
        return wrapper
    return auth_deco


#auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
#就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
@auth(auth_type='ldap')
def index():
    print('欢迎来到主页面')

@auth(auth_type='ldap')
def home():
    print('这里是你家')

def shopping_car():
    print('查看购物车啊亲')

def order():
    print('查看订单啊亲')

# print(user_list)
index()
# print(user_list)
home()

 

 

 

 

 

       

http://www.bkjia.com/Pythonjc/1208960.htmlwww.bkjia.comtruehttp://www.bkjia.com/Pythonjc/1208960.htmlTechArticlePython 基础 装饰器,python基础装饰器
后天把学过的装饰器的学识进行回想一下,谈到装饰器,第三反馈正是以此事物吗便是用来装逼的,为…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图