python装饰器

2023-05-16

今天看了一些函数装饰器的知识,第一遍没看懂,后来才一点点弄明白。。。

首先,函数也是对象,所以可以返回函数

def hello(func):  #func是函数名

    def h():#在函数内部的函数

        print 'hello world'

        func()

    return h

@hello

def d():

    print 'charles dong !'

d() 

输出:

‘hello world’

‘charles dong’

装饰器也可以有参数

def deco(arg):#arg='mymodule'
def _deco(func):#func=myfunc()
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." )

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

第一步:最简单的函数,准备附加额外功能

?
1
2
3
4
5
6
7
8
# -*- coding:gbk -*-
'''示例1: 最简单的函数,表示调用了两次'''
def myfunc():
print ( "myfunc() called." )
myfunc()
myfunc()

第二步:使用装饰函数在函数执行前和执行后分别附加额外功能

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- 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()

第三步:使用语法糖@来装饰函数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- 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()

第四步:使用内嵌包装函数来确保每次新函数都被调用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- 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()

第五步:对带参数的函数进行装饰

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- 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 )

第六步:对参数数量不确定的函数进行装饰

?
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
# -*- 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 )

第七步:让装饰器带参数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- 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()

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

?
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
# -*- 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文件中,同时演示了对一个函数应用多个装饰器

?
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
# -*- 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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- 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 ))

实现一个装饰器d2使下面的代码打印相应的结果:

 @d2('a', 'b')

def test(arg1, arg2):

    print 'test', arg1, arg2

 

test('c', 'd')

 

[output]

before test a b

test c d

[/output]


def d2(a,b):

    def dd2(func):

        def ddd2(arg1,arg2):

            print '[output]'

            print 'befot test', a, b

            test(argv1, argv2)

            print '[/output]'

            return ddd2

    return dd2


 

转载于:https://my.oschina.net/u/240562/blog/69221

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python装饰器 的相关文章

随机推荐

  • 基于深度学习的合成孔径雷达自聚焦

    文章目录 引言什么是合成孔径雷达什么是自聚焦 经典自聚焦方法基于机器学习的方法基于极速学习机的方法基于深度学习的SAR自聚焦 代码附录 引言 本文全面介绍合成孔径雷达自聚焦概念和方法 想获取更为详尽的描述 xff0c 请参考以下几篇论文 如
  • IEEE 论文排版之LaTeX模板

    说明 主要介绍IEEE LaTeX论文模板的使用 获取模板 IEEE的所有期刊 会议 杂志的模板都可以从 IEEE Template Selector 页面获得 xff0c 以期刊 IEEE Transactions on Geoscien
  • 基于 YOLOv2 Tiny的车牌检测

    文章目录 YOLO安装源码获取安装 车牌检测转换样本格式修改网络其它 训练可视化训练测试 YOLO安装 源码获取 从 darknet 下载 span class token function git span clone https git
  • docker 权限问题 Got permission denied while trying to connect to the Docker daemon socket at 。。。

    在用户权限下docker 命令需要 sudo 否则出现以下问题 通过将用户添加到docker用户组可以将sudo去掉 xff0c 命令如下 sudo groupadd docker 添加 docker 用户组 sudo gpasswd a
  • NAT模式,主机无法ping虚拟机,虚拟机可以ping主机

    原因 xff1a 虚拟机指定的虚拟网络和本机网络连接中的虚拟网卡未对应 xff0c 或网段不一致 解决 xff1a 在网络连接中找用于虚拟NAT网络下的虚拟网卡 xff08 我这里是VMnet2 xff0c 也有可能是VMnet8 xff0
  • zeromq 利用protobuf通信

    利用zeromq进行编程时候 xff0c 服务器和客户端的通信 xff0c 利用protobuf时候 之前的项目里面 xff0c 需要对protobuf进行编码解码 其实并不需要如此繁琐 xff0c 直接利用 protobuf里面的 Mes
  • 游戏升级之路

    七十一雾央原创 转载请注明 http blog csdn net hust xy 楼主学习编程有两年了 xff0c 决定向游戏发展大概就是半年前了 xff0c 在这里总结一下游戏方面的学习经历过 xff0c 给初学的朋友们参考下 xff0c
  • windows7远程桌面访问ubuntu16.04

    1 安装xrdp sudo apt get install xrdp xff12 安装vnc4server sudo apt get install vnc4server 3 安装xubuntu desktop sudo apt get i
  • <1> GCC的源码安装

    当我们安装好操作系统基本自带了gcc的编译器 由于版本和root 权限的问题 我们希望在自己的目录下创建一个相对独立的environment 这样我们更新起来也会比较方便 要安装基本gcc 首先要gmp mpfr和mpc xff08 ftp
  • TouchGFX使用心得(8)——通配符的中文显示(呕心沥血)

    这里写目录标题 前言方法一需要注意的问题 xff08 非常重要 xff01 xff01 xff01 xff01 xff09 方法二官方文档具体操作加载二进制文件通配符的显示放入stm32 总结 前言 通配符的中文的显示是我一直很疑惑的 xf
  • 9月10日美团网2014校招研发笔试哈尔滨站

    1 链表翻转 给出一个链表和一个数k xff0c 比如链表1 2 3 4 5 6 xff0c k 61 2 xff0c 则翻转后2 1 4 3 6 5 xff0c 若k 61 3 翻转后3 2 1 6 5 4 xff0c 若k 61 4 x
  • 2014校园招聘京东软件开发类笔试(完整版)

    时间 xff1a 2013 9 10 2013 10 8 地点 xff1a 四川大学 天津大学 职位 xff1a 软件开发工程师岗 语言 xff1a java 1 A 2 C 3 D 4 B 5 A 二 1 B 三1 D 2 B 3 C 4
  • 阅读科研文献心得分享(二)

    心得一 每天还保持读至少2 3篇的文献的习惯 读文献有不同的读法 但最重要的自己总结概括这篇文献到底说了什么 xff0c 否则就是白读 读的时候好像什么都明白 xff0c 一合上就什么都不知道 这是读文献的大忌 xff0c 既浪费时间 xf
  • 云数据库怎么挑选

    from http www chinacloud cn show aspx id 61 13222 amp cid 61 17 将数据库服务器在IaaS云上运行好吗 xff1f 或者应该转换成PaaS选择 xff1f 数据库即服务的选择可能
  • C# FTP操作(上传、下载等……)

    因为工作中经常涉及到FTP文件的上传和下载 xff0c 每次有这样的需求时都要重复编写相同的代码 xff0c 后来干脆整理一个FTPClass xff0c 这样不仅方便自己使用 xff0c 也可以共享给部门其它同事 xff0c 使用时直接调
  • 通过tasksel一键下载lamp(未成功)

    首先可以通过apt安装tasksel 安装 xff1a sudo apt install tasksel 通过taskel的方式安装lamp server全包 taskel的安装方式和apt get的有类似但是还是有区别个人觉得他像是apt
  • qemu创建快照后删除快照导致qemu crashed的BUG

    问题描述 启动一个虚拟机 创建三个快照 删除第一个快照时报错 合并磁盘失败 通过测试 创建虚拟机 ubuntu1604 win7 启动虚拟机 创建两个快照 删除第一个快照 瘦终端自自动关闭 vdsm报错如下 2018 07 20 17 00
  • 群晖docker容器内配置ubuntu远程桌面访问

    群晖docker容器内配置ubuntu远程桌面访问 当希望在群晖docker内的ubuntu开启远程桌面访问时 xff0c 和一般云服务器桌面安装方式还是有所区别 这里ubuntu的版本为14 04 LTS xff0c 由于nas性能较弱
  • Elasticsearch 7.6.0 最详细安装及配置(HA)安装与启动

    Elasticsearch 7 6 0 最详细安装及配置 xff08 HA xff09 安装与启动 Elasticsearch是一个非常好用的搜索引擎 xff0c 和Solr一样 xff0c 他们都是基于倒排索引的 今天我们就看一看Elas
  • python装饰器

    今天看了一些函数装饰器的知识 xff0c 第一遍没看懂 xff0c 后来才一点点弄明白 首先 xff0c 函数也是对象 xff0c 所以可以返回函数 def hello func func是函数名 def h xff1a 在函数内部的函数