Python自定义注解

Python3.0之后加入新特性Decorators,以@为标记修饰function和class。有点类似c++的宏和java的注解。Decorators用以修饰约束function和class,分为带参数和不带参数,影响原有输出,例如类静态函数我们要表达的时候需要函数前面加上修饰@staticmethod或@classmethod,为什么这样做呢?下面用简单的例子来看一下,具体内容可以查看:官方解释

不带参数的单一使用

def spamrun(fn):
    def sayspam(*args): print("spam,spam,spam") fn(*args) return sayspam @spamrun def useful(a,b): print(a*b) if __name__ == "__main__" useful(2,5) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行结果

spam,spam,spam
10
  • 1
  • 2

函数useful本身应该只是打印10,可是为什么最后的结果是这样的呢,其实我们可以简单的把这个代码理解为

def spamrun(fn):
    def sayspam(*args): print("spam,spam,spam") fn(*args) return sayspam def useful(a,b): print(a*b) if __name__ == "__main__" useful = spamrun(useful) useful(a,b)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

不带参数的多次使用

def spamrun(fn):
    def sayspam(*args): print("spam,spam,spam") fn(*args) return sayspam def spamrun1(fn): def sayspam1(*args): print("spam1,spam1,spam1") fn(*args) return sayspam1 @spamrun @spamrun1 def useful(a,b): print(a*b) if __name__ == "__main__" useful(2,5) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

运行结果

spam,spam,spam
spam1,spam1,spam1
10
  • 1
  • 2
  • 3

这个代码理解为

if __name__ == "__main__"
  useful = spamrun1(spamrun(useful))
  useful(a,b)
  • 1
  • 2
  • 3

带参数的单次使用

def attrs(**kwds):
    def decorate(f): for k in kwds: setattr(f, k, kwds[k]) return f return decorate @attrs(versionadded="2.2", author="Guido van Rossum") def mymethod(f): print(getattr(mymethod,'versionadded',0)) print(getattr(mymethod,'author',0)) print(f) if __name__ == "__main__" mymethod(2) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

运行结果

2.2
Guido van Rossum
2
  • 1
  • 2
  • 3

这个代码理解为

if __name__ == "__main__"
  mymethod = attrs(versionadded="2.2",
          author="Guido van Rossum).(mymethod)
  mymethod(2)
  • 1
  • 2
  • 3
  • 4

带参数的多次使用 
这次我们来看一个比较实际的例子,检查我们函数的输入输出是否符合我们的标准,比如我们希望的输入是(int,(int,float))输出是(int,float),这个例子在官网里有,但是在3.6版本中使用有些问题,这里进行了一些改动,如果要进一步了解可以看下functionTool。

def accepts(*types):
    def check_accepts(f): def new_f(*args, **kwds): assert len(types) == (len(args) + len(kwds)), \ "args cnt %d does not match %d" % (len(args) + len(kwds), len(types)) for (a, t) in zip(args, types): assert isinstance(a, t), \ "arg %r does not match %s" % (a, t) return f(*args, **kwds) update_wrapper(new_f, f) return new_f return check_accepts def returns(rtype): def check_returns(f): def new_f(*args, **kwds): result = f(*args, **kwds) assert isinstance(result, rtype), \ "return value %r does not match %s" % (result, rtype) return result update_wrapper(new_f, f) return new_f return check_returns @accepts(int, (int, float)) @returns((int, float)) def func(arg1, arg2): return arg1 * arg2 if __name__ == "__main__" a = func(1, 'b') print(a) 
  • 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

这里故意输入了错误的参数,所以运行结果将我们的断言打印了出来

AssertionError: arg 'b' does not match (<class 'int'>, <class 'float'>)
  • 1

这个代码理解为

if __name__ == "__main__"
  func = accepts(int, (int, float)).(accepts((int, float)).(mymethod)) a = func(1, 'b') print(a)
  • 1
  • 2
  • 3
  • 4

说到这里,大家不难看出其实我们可以使用Decorators做很多工作,简化代码,使逻辑更清晰等。还有更多的用法等着大家自己去挖掘了,这里只简单的介绍了针对函数的用法,其实还可以针对class使用,具体的大家自己看看官方介绍,结合这篇文档应该就不难理解了。

 

引自:https://blog.csdn.net/u013474436/article/details/75675113

转载于:https://www.cnblogs.com/qiumingcheng/p/11587647.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值