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

Python自定义注解的更多相关文章

  1. 自定义注解-方法重试@RetryProcess

    背景 在项目开发中,有时候会出现接口调用失败,本身调用又是异步的,如果是因为一些网络问题请求超时,总想可以重试几次把任务处理掉. 一些RPC框架,比如dubbo都是有重试机制的,但是并不是每一个项目多 ...

  2. java自定义注解类

    一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...

  3. Jackson 通过自定义注解来控制json key的格式

    Jackson 通过自定义注解来控制json key的格式 最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换.而这个替换过程是需要依赖一个第三方的dubbo服务的.为了使得这个转换 ...

  4. 自定义注解之运行时注解(RetentionPolicy.RUNTIME)

    对注解概念不了解的可以先看这个:Java注解基础概念总结 前面有提到注解按生命周期来划分可分为3类: 1.RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成clas ...

  5. JAVA自定义注解

    在学习使用Spring和MyBatis框架的时候,使用了很多的注解来标注Bean或者数据访问层参数,那么JAVA的注解到底是个东西,作用是什么,又怎样自定义注解呢?这篇文章,即将作出简单易懂的解释. ...

  6. 用大白话聊聊JavaSE -- 自定义注解入门

    注解在JavaSE中算是比较高级的一种用法了,为什么要学习注解,我想大概有以下几个原因: 1. 可以更深层次地学习Java,理解Java的思想. 2. 有了注解的基础,能够方便阅读各种框架的源码,比如 ...

  7. [javaSE] 注解-自定义注解

    注解的分类: 源码注解 编译时注解 JDK的@Override 运行时注解 Spring的@Autowired 自定义注解的语法要求 ① 使用@interface关键字定义注解 ② 成员以无参无异常方 ...

  8. 使用spring aspect控制自定义注解

    自定义注解:这里是一个处理异常的注解,当调用方法发生异常时,返回异常信息 /** * ErrorCode: * * @author yangzhenlong * @since 2016/7/21 */ ...

  9. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

随机推荐

  1. url中拼接中文参数,后台接收为乱码的问题

    遇到在URL中拼接中文的参数,后台拿到的数据为乱码的问题,这里来说一下问题出现的原因与解决方法. 大家比较关心的应该是解决的方法,因此先说解决方法. 解决方法 解决的方法是在客户端对这个中文参数进行编 ...

  2. 列举常见国内外做服务器与存储的IT厂家

    列举常见国内外做服务器与存储的IT厂家 联想.浪潮.曙光.同有飞骥.迪菲特.宝德.星盈.元谷.威联通.群晖.忆捷.天敏等 华为.华三.戴尔.神州云科.同有.谷数,都是比较大的厂商 HDS(昆仑联通). ...

  3. 适合初学者的Python爬取链家网教程

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TinaLY PS:如有需要Python学习资料的小伙伴可以加点击下 ...

  4. String字符串是不变对象,内容一旦创建不可改变,若改变一定会创建新对象

    package seday01;/** * 字符串是不变对象,内容一旦创建不可改变,若改变一定会创建新对象* @author xingsir */public class StringDemo { p ...

  5. 滴滴出行开源项目doraemonkit食用指南

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/94 doraemonkit 功能介绍 一两周前在地铁上刷任 ...

  6. driver.find_element_by_xpath() 带参数时的写法

    假设要定位如下所示的 Elements,且文本 “1234567890” 对应参数 cluster_name: <td  class="xxxx-body">12345 ...

  7. xml的建模

    xml建模的思路 1.分析需要被建模的文件中有那几个对象 2.每个对象拥有的行为以及属性 3.定义对象从小到大(从里到外) 4.通过23种的设计模式中的工厂模式,解析xml生产出指定对象 建模的好处 ...

  8. SQL必知必会|SQL基础篇

    了解SQL DBMS的前世今生 SQL是如何执行的 DDL语法 关于外键的性能问题? 是否使用外键确实会有一些争议.关于外键的使用: 首先,外键本身是为了实现强一致性,所以如果需要正确性>性能的 ...

  9. Html学习之五(嵌套之简单购物界面设计)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. oracle 数据库下所有表结构、数据量及缺失值统计

    表结构 SELECT t1.TABLE_NAME, t1.COLUMN_NAME, t1.DATA_TYPE || '(' || t1.DATA_LENGTH || ')', t2.COMMENTS ...