• 【从C#走进Python】四、装饰器


      Python装饰器,是指在方法上面写的@开头的一行,或者说@装饰器名。

      我看廖雪峰的python教程,可以说看得我对装饰器一无所知吧,每个人的讲述方式并不一定就适合其他人,或者说,师傅领进门,修行看个人。

      Python特性这本书,在装饰器上说得很明白,@是个语法糖。

     

    Python装饰器

    语法糖本质

    格式:在方法定义上一行,@开头加函数名

    作用:如果方法上方添加了装饰器,那么在执行函数的时候,会把函数结果作为入参进入装饰器的(方法)内容中。

    >>> def testDecorate(func):
    ...     print('--------')
    ...     func()
    ...     print('--------')
    >>> @testDecorate
    ... def yell():
    ...     print('hello');
    ...
    --------
    hello
    --------

    等价于:

    >>> def testDecorate(func):
    ...     print('--------')
    ...     func()
    ...     print('--------')
    >>> def yell():
    ...     print('hello');
    ...
    >>> testDecorate(yell)
    --------
    hello
    --------

    闭包:

    >>> def testDecorate0(func):
    ...     def wrapper():
    ...         print('--------')
    ...         func()
    ...         print('--------')
    ...     return wrapper
    ...
    >>> @testDecorate0
    ... def yell():
    ...     print('hello')
    ...
    >>> yell()
    --------
    hello
    --------

     看不见被包装的函数名字

    >>> yell
    <function testDecorate0.<locals>.wrapper
    at 0x0000000002DF4AE8>

    嵌套:(多个装饰器时,当层入参取下一层出参)

    >>> def upperDecorate(func):
    ...     def wrapper():
    ...         return func().upper()
    ...     return wrapper
    ...
    >>> def printDecorate(func):
    ...     def wrapper():
    ...         print(func())
    ...     return wrapper
    ...
    ... >>> @testDecorate0
    ... @printDecorate
    ... @upperDecorate
    ... def yell():
    ...     return 'hello'
    ...
    >>> yell()
    --------
    HELLO
    --------

    等价于:

    >>> def yell():
    ...     return 'hello'
    ...
    >>> decorated = testDecorate0(
    printDecorate(upperDecorate(yell)))
    >>> decorated()
    --------
    HELLO
    --------

      这种设计感觉有些危险,毕竟我不知道下一层的出参是什么,想不到很好地使用场景。

    @property

    >>> class test:
    ...     def __init__(self):
    ...         self.name = 'test'
    ...     @property
    ...     def name1(self):
    ...         return self.name
    ...     @name1.setter
    ...     def name2(self, value):
    ...         self.name = value
    ...
    >>> class test0():
    ...     def __init__(self):
    ...         self.name = 'test0'
    ...
    >>> t0 = test0()
    >>> t0.name
    'test0'
    >>> t = test()
    >>> t.name1 = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: can't set attribute
    >>> t.name = 2
    >>> t.name1
    2

    是可以直接写个get方法和set方法,

    但在python编程上习惯不是这样, pythonic一些的做法是使用内置的@property装饰器。

    这个装饰器是使方法变成属性来访问,

    相当于一个get方法;

    同时可以设置set方法来限制赋值。

    下图有个使用的示例:

      

    @staticmethod

    类方法可以使用@classmethod装饰,

    静态方法使用@staticmethod修饰,

    注意的是,类方法需要传入cls(解释器认为首个入参就是cls类对象)

    静态方法的入参就随需求了,它与类的其他所有内容都没有关系。

    >>> class test01:
    ...     def __init__(self, name):
    ...         self.name = name
    ...     @staticmethod
    ...     def staticMethod():
    ...         print('staticMethod called')
    ...     @classmethod
    ...     def classMethod(cls):
    ...         print(f'classMethod is called, {cls}')
    ...         return cls('cat')
    ...
    >>> dir(test01)
    [...
    'classMethod', 'staticMethod']
    >>> dir(test01('dog'))
    [...
    'classMethod', 'name', 'staticMethod']
    >>> test01.classMethod()
    classMethod is called, <class '__main__.test01'>
    <__main__.test01 object at 0x0000000002DE8EB8>
    >>> _.name
    'cat'

    注:类对象、实例对象均可调用类方法、静态方法

      让人比较遗憾的还是链式方法(像C#的拓展方法,可以做到instance.funcA().funcB().funC(),实例作为.后方法的入参,匹配到实例方法、或类方法,或程序集上的所有静态方法),但是Python没有这种方式,只能“套娃”(像funcC (funcB(funcA(instance)))),尽管也可以套多个装饰器,但从阅读性上来说,有点难看。

  • 相关阅读:
    Elasticsearch学习之深入搜索三 --- best fields策略
    Elasticsearch学习之深入搜索二 --- 搜索底层原理剖析
    Elasticsearch学习之深入搜索一 --- 提高查询的精准度
    Elasticsearch学习之深入聚合分析五---案例实战
    Enigma Virtual Box:生成可执行文件。
    erlang的erl文件的编码方式
    Java相关术语 或者 组件命。
    pyqt5加载网路图片,不本地下载。
    Python3 的json 和 PHP的json
    python3 post方式上传文件。
  • 原文地址:https://www.cnblogs.com/carmen-019/p/13296518.html
Copyright © 2020-2023  润新知