zoukankan      html  css  js  c++  java
  • python内置装饰器@property

    前言

    今天来说一下@property装饰器,这是个python内置的装饰器,主要是作用是把类中的一个方法变为类中的一个属性,并且使定义属性和修改现有属性变的更容易

    我们可以看一下@property源码中给的实例和解释

     1 Decorators make defining new properties or modifying existing ones easy:
     2 
     3 
     4 class C(object):
     5     @property
     6     def x(self):
     7         "I am the 'x' property."
     8         return self._x
     9 
    10     @x.setter
    11     def x(self, value):
    12         self._x = value
    13 
    14     @x.deleter
    15     def x(self):
    16         del self._x

    没错,龟叔给的解释就是这个装饰器会把定义新属性和对现有的属性的修改变的更简单,那么传统的方法在绑定属性和访问属性时是什么样的呢?

    实例

    14 class UserInfo(object):
    15 
    16     def get_name(self):
    17         """通过类的方法访问类中的属性"""
    18         return self.__name
    19 
    20     def set_name(self, name):
    21         """通过外部传参的方式绑定属性"""
    22         self.__name = name
    23 
    24 
    25 if __name__ == '__main__':
    26     user = UserInfo()
    27     # 绑定name属性
    28     user.set_name(["超哥", "linux超"])
    29     print("我的名字是:", user.get_name())

    执行结果

    我的名字是: [’超哥’, ‘linux超’]
    
    Process finished with exit code 0

    这种方式在绑定属性,获取属性时显的很是繁琐,而且无法保证数据的准确性,从执行结果看来,名字应该是个字符串才对,然而输出结果却是个列表,这并不符合实际规则

    而且也没有通过直接访问属性,修改属性的方式那么直观

    我们对代码稍作改动,并使用@property装饰器来实现

    14 class UserInfo(object):
    15     @property
    16     def name(self):
    17         return self.__name
    18 
    19     @name.setter
    20     def name(self, name):
    21         if isinstance(name, str):
    22             self.__name = name
    23         else:
    24             raise TypeError("The name must be str")
    25 
    26 
    27 if __name__ == '__main__':
    28     user = UserInfo()
    29     # 绑定属性
    30     user.name = "linux超"
    31     print("我的名字是", user.name)
    32     user.name = ["linux超", "超哥"]
    33     print("我的名字是", user.name)

    执行结果

    我的名字是 linux超
    Traceback (most recent call last):
      File "D:/LingMengPython16/LingMengPython16/cnblogs/python_class.py", line 32, in <module>
        user.name = ["linux超", "超哥"]
      File "D:/LingMengPython16/LingMengPython16/cnblogs/python_class.py", line 24, in name
        raise TypeError("The name must be str")
    TypeError: The name must be str
    
    Process finished with exit code 1

    经过优化后的代码我们可以看到当绑定的属性并非是一个字符串类型时,就会报错,而且我们可以直接通过类似访问属性的方式来绑定属性,访问属性,这样就更加直观了

    这里有个点需要注意,@name.setter中name这个名字极其被他修饰的方法名字与@property修改的方法名必须保持一致,否则会报错

    其中@name.setter装饰器是因为使用了@property后他本身创建的装饰器

    其实呢,我觉得@perproty装饰器并不仅仅只用来绑定属性和访问属性,还可以用来在类的外部访问私有成员属性

    先来看个类的外部直接访问私有成员的实例

    14 class UserInfo(object):
    15 
    16     def __init__(self, name, age):
    17         self.__name = name
    18         self.__age = age
    19 
    20 if __name__ == '__main__':
    21     user = UserInfo('linux超', 18)
    22     print(user.__name)

    执行结果

    Traceback (most recent call last):
      File "D:/LingMengPython16/LingMengPython16/cnblogs/python_property.py", line 22, in <module>
        print(user.__name)
    AttributeError: 'UserInfo' object has no attribute '__name'
    
    Process finished with exit code 1

    没错,程序是没办法运行成功的,因为python不允许你在类的外部访问类中的私有成员,这么做其实是为了保护数据的安全性

    那么这时候我们也可以使用@property装饰器来访问类的属性

    14 class UserInfo(object):
    15 
    16     def __init__(self, name):
    17         self.__name = name
    18 
    19     @property
    20     def name(self):
    21         """通过类的方法访问类中的私有属性"""
    22         return self.__name
    23 
    24 if __name__ == '__main__':
    25     user = UserInfo('linux超')
    26     print("获取name属性:", user.name)

    执行结果

    获取name属性: linux超
    
    Process finished with exit code 0

    这样就能访问类的私有成员属性了

    那么其实我个人认为,相对于绑定属性来说这种方式用的比较多,当你不想子类继承父类时,防止子类修改父类的属性,那么你完全就可以使用这种方法来避免属性被修改,而且在子类和类的外部还可以正常访问这个私有属性

    总结

    @property装饰器主要用来改变一个方法为一个属性,且需要注意几点

    1. 被此装饰器装饰的方法不能传递任何除self外的其他参数

    2.当同时使用@property和@x.setter时 需要保证x以及被@x.setter修改的方法名字与@property修改的方法名字必须保持一致

  • 相关阅读:
    dell台式机网络唤醒
    今天学习到ROS的PCC的新的一种场景,用PCC不是为了带宽叠加而是为了换IP,PCC的标准做法
    默认ros安装好以后,可能对外开放的端口号,可能被黑客利用的地方,ros的0day漏洞
    ros-winbox利用防火墙安全登录,二次碰撞方法
    S5120V2-IRF2配置
    routeros ros mikrotik的ipsec配置,注意配置的步骤,以及哪些硬件支持哪种加速
    60岁-80岁老年人住院医疗险,既往症可理赔!家有长辈首选
    docker上2分钟安装mikrotik routeros
    pandas filter数据筛选
    (纪录片)光的故事 BBC Light Fantastic (2004)
  • 原文地址:https://www.cnblogs.com/dancesir/p/13645653.html
Copyright © 2011-2022 走看看