• 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

  • 相关阅读:
    浅谈Java中的equals和==与hashCode
    数组操作
    python-类
    javascript操控浏览器
    javascript_获取浏览器属性
    javascript_data
    python3_phantomJS_test
    python检测字符串的字母
    python百分比数比较大小
    selenium加载时间过长
  • 原文地址:https://www.cnblogs.com/qiumingcheng/p/11587647.html
Copyright © 2020-2023  润新知