【Python】Python中的注解“@”

来源:互联网 发布:福建摩尔软件靠谱吗 编辑:程序博客网 时间:2024/06/13 21:52

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

不带参数的单一使用

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

运行结果

  1. spam,spam,spam
  2. 10

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

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

不带参数的多次使用

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

运行结果

  1. spam,spam,spam
  2. spam1,spam1,spam1
  3. 10

这个代码理解为

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

带参数的单次使用

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

运行结果

  1. 2.2
  2. Guido van Rossum
  3. 2

这个代码理解为

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

带参数的多次使用

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

  1. def accepts(*types):
  2. def check_accepts(f):
  3. def new_f(*args, **kwds):
  4. assert len(types) == (len(args) + len(kwds)),
  5. "args cnt %d does not match %d" % (len(args) + len(kwds), len(types))
  6. for (a, t) in zip(args, types):
  7. assert isinstance(a, t),
  8. "arg %r does not match %s" % (a, t)
  9. return f(*args, **kwds)
  10. update_wrapper(new_f, f)
  11. return new_f
  12. return check_accepts
  13. def returns(rtype):
  14. def check_returns(f):
  15. def new_f(*args, **kwds):
  16. result = f(*args, **kwds)
  17. assert isinstance(result, rtype),
  18. "return value %r does not match %s" % (result, rtype)
  19. return result
  20. update_wrapper(new_f, f)
  21. return new_f
  22. return check_returns
  23. @accepts(int, (int, float))
  24. @returns((int, float))
  25. def func(arg1, arg2):
  26. return arg1 * arg2
  27. if __name__ == "__main__"
  28. a = func(1, 'b')
  29. print(a)

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

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

这个代码理解为

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

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

转自:http://www.jcodecraeer.com/a/chengxusheji/chengxuyuan/2017/0418/7842.html

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 煤气灶点火针更换 热水器不点火是怎么回事 燃气热水器点火失败 点火开关价格 汽车怎么点火 煤气灶点火针 奥运会射箭点火 烧烤怎么点火 4缸发动机点火顺序 燃烧机点火针 普桑点火线圈价格 柴油机点火方式 汽车怎样点火 手动挡汽车点火 悦翔v3点火线圈价格 烧掉他们怎么点火 巫师3魔法之灯点火顺序图 燃气热水器不点火 万和热水器不点火 美的热水器不点火 燃气热水器不点火怎么回事 方太燃气灶不点火 燃气热水器不点火什么原因 燃气灶不打火且没有点火声 天然气壁挂炉不点火 樱花燃气热水器不点火 燃气热水器无法点火 自动挡的车怎么点火 点灯人 点灯节 缅甸点灯节 点灯 母亲点灯 瞎子点灯 点灯祈愿文 盲人点灯 星星点灯歌词 不许百姓点灯 星星点灯郑智化 星星点灯歌曲 星星点灯吉他谱