• 装饰器


    常见的3种装饰器@property、@staticmethod、@classmethod的作用:

      1、  @property 装饰过的函数返回的不再是一个函数,而是一个property对象装饰过后的方法不再是可调用的对象,可以看做数据属性直接访问。

    示例代码:

    class Rectangle:
        def __init__(self,width,height):
            self.width = width
            self.height = height
            
        def area(self):
            return self.width*self.height
    
        def __add__(self,other):
            if isinstance(other,Rectangle):
                return self.area()+other.area()
    
    C1 = Rectangle(3,4)
    
    #输出结果:
    ==================== RESTART: D:/Python36/note/装饰器002.py ====================
    >>> C1.area()
    12
    >>> C1.area
    <bound method Rectangle.area of <__main__.Rectangle object at 0x0000000002B38550>>
    >>> C1.width
    3
    >>> C1.height
    4
    >>> 

    在用没有使用装饰器时候,类中的方法和属性用上述方式调用,接下来用装饰器@property来装饰方法area

     1 class Rectangle:
     2     def __init__(self,width,height):
     3         self.width = width
     4         self.height = height
     5         
     6     @property
     7     def area(self):
     8         return self.width*self.height
     9 
    10     def __add__(self,other):
    11         if isinstance(other,Rectangle):
    12             return self.area()+other.area()
    13 
    14 C1 = Rectangle(3,4)
    15 
    16 #输出结果:
    17 >>> C1.area
    18 12
    19 >>> C1.area()
    20 Traceback (most recent call last):
    21   File "<pyshell#134>", line 1, in <module>
    22     C1.area()
    23 TypeError: 'int' object is not callable
    24 >>> C1.height
    25 4
    26 >>> C1.width
    27 3
    28 >>> 

    通过用装饰器@property装饰之后,类中的方法area可以用原来调用属性的方式进行调用,而用方法本身调用的方式反而报错,这说明装饰器将类中的方法变成了一种属性

    2、@staticmethod 把没有参数的函数装饰过后变成可被实例调用的函数,函数定义时是没有参数的。

     1 class Rectangle:
     2     def __init__(self,width,height):
     3         self.width = width
     4         self.height = height
     5         
     6     @property
     7     def area(self):
     8         return self.width*self.height
     9 
    10     def __add__(self,other):
    11         if isinstance(other,Rectangle):
    12             return self.area()+other.area()
    13 
    14     def fun():
    15         return '没有参数的函数输出'
    16 
    17 C1 = Rectangle(3,4)
    18 
    19 #输出结果:
    20 >>> C1.fun
    21 <bound method Rectangle.fun of <__main__.Rectangle object at 0x0000000002B386D8>>
    22 >>> C1.fun()
    23 Traceback (most recent call last):
    24   File "<pyshell#142>", line 1, in <module>
    25     C1.fun()
    26 TypeError: fun() takes 0 positional arguments but 1 was given
    27 >>> 

     从上面的代码中可以发现没有类中没有参数的函数fun虽然可以直接通过类名.函数名来访问,但是输出的对象不能容易识别的内容,而直接通过类名.函数名()就会报错,这里通过静态方法@staticmethod来装饰一下,再继续看效果:

    class Rectangle:
        def __init__(self,width,height):
            self.width = width
            self.height = height
            
        @property
        def area(self):
            return self.width*self.height
    
        def __add__(self,other):
            if isinstance(other,Rectangle):
                return self.area()+other.area()
        @staticmethod
        def fun():
            return '没有参数的函数输出'
    
    C1 = Rectangle(3,4)
    
    #输出结果:
    >>> C1.fun
    <function Rectangle.fun at 0x0000000002DCF840>
    >>> C1.fun()
    '没有参数的函数输出'
    >>> 

    3、@classmethod 把装饰过的方法变成一个classmethod类对象,既能被类调用又能被实例调用。注意参数是cls代表这个类本身。而是用实例的方法只能被实例调用。

      

    class Rectangle:
        def __init__(self,width,height):
            self.width = width
            self.height = height
            
        @property
        def area(self):
            return self.width*self.height
    
        def __add__(self,other):
            if isinstance(other,Rectangle):
                return self.area()+other.area()
            
        @staticmethod
        def fun():
            return '没有参数的函数输出'
    
        
        def show():
            return '类方法返回值'
    
    C1 = Rectangle(3,4)
    
    #调用show方法输出结果:
    >>> Rectangle.show
    <function Rectangle.show at 0x0000000002BCF8C8>
    >>> Rectangle.show()
    '类方法返回值'
    >>> C1.show
    <bound method Rectangle.show of <__main__.Rectangle object at 0x0000000002B38710>>
    >>> C1.show()
    Traceback (most recent call last):
      File "<pyshell#177>", line 1, in <module>
        C1.show()
    TypeError: show() takes 0 positional arguments but 1 was given
    >>> 

    类直接调用show方法是可以的,但是通过实例C1调用则发现报错,这里我们通过装饰器@classmethod装饰后,再看效果:

     1 class Rectangle:
     2     def __init__(self,width,height):
     3         self.width = width
     4         self.height = height
     5         
     6     @property
     7     def area(self):
     8         return self.width*self.height
     9 
    10     def __add__(self,other):
    11         if isinstance(other,Rectangle):
    12             return self.area()+other.area()
    13         
    14     @staticmethod
    15     def fun():
    16         return '没有参数的函数输出'
    17 
    18     @classmethod
    19     def show(cls):
    20         return '类方法返回值'
    21 
    22 C1 = Rectangle(3,4)
    23 
    24 #调用show方法输出结果:
    25 >>> Rectangle.show
    26 <bound method Rectangle.show of <class '__main__.Rectangle'>>
    27 >>> Rectangle.show()
    28 '类方法返回值'
    29 >>> C1.show
    30 <bound method Rectangle.show of <class '__main__.Rectangle'>>
    31 >>> C1.show()
    32 '类方法返回值'
    33 >>> 

    发现通过装饰器@classmethod装饰后,show方法不仅可以被类直接调用,而且也可以被对象C1调用,证明了@classmethod装饰器能将类中的方法转换成既能被类调用也能被示例调用

    4、内嵌函数(闭包)

    def fun1(x):
        def fun2(y):
            return x*y
        return fun2
    
    #运行结果:
    >>> fun1(2)
    <function fun1.<locals>.fun2 at 0x0000000001CF3E18>
    >>> fun1(2)(3)
    6
    >>> fun1(2)
    <function fun1.<locals>.fun2 at 0x0000000001CF3E18>
    >>> 

    函数fun1运行后返回的值是另外一个函数fun2,即:<function fun1.<locals>.fun2 at 0x0000000001CF3E18>,接着在该对象后面继续赋值?(3),即调用函数fun2(3)此时返回 x*y的值,所以此时最终返回值为6,即从外面外里面传参数,然后把里面函数结果返回到外面,这就是闭包,整体的结构中fun2就是内嵌函数。

  • 相关阅读:
    漫谈 IP 协议
    Git常用组合操作
    my questions of C#
    关于C#多态的思考
    设计模式:示例与思考
    C#环境搭建,以及C#编译器的使用
    网络模型和TCP协议族
    Understanding TCP/IP Network Stack
    Get on the CORBA
    Introduction to COBRA
  • 原文地址:https://www.cnblogs.com/kindnull/p/6813149.html
Copyright © 2020-2023  润新知