手机版
你好,游客 登录 注册
背景:
阅读新闻

Python内置装饰器@property

[日期:2019-08-25] 来源:cnblogs.com/linuxchao  作者:linux超 [字体: ]

前言

今天来说一下@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

复制代码

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

实例


复制代码
 1 """
 2 ------------------------------------
 3 @Time : 2019/7/4 20:57
 4 @Auth : linux超
 5 @File : python_property.py
 6 @IDE  : PyCharm
 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
 8 @QQ  : 28174043@qq.com
 9 @GROUP: 878565760
10 ------------------------------------
11 """
12
13
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装饰器来实现


复制代码
 1 """
 2 ------------------------------------
 3 @Time : 2019/7/4 22:02
 4 @Auth : linux超
 5 @File : python_class.py
 6 @IDE  : PyCharm
 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
 8 @QQ  : 28174043@qq.com
 9 @GROUP: 878565760
10 ------------------------------------
11 """
12
13
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装饰器并不仅仅只用来绑定属性和访问属性,还可以用来在类的外部访问私有成员属性

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


复制代码
 1 """
 2 ------------------------------------
 3 @Time : 2019/7/4 20:57
 4 @Auth : linux超
 5 @File : python_property.py
 6 @IDE  : PyCharm
 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
 8 @QQ  : 28174043@qq.com
 9 @GROUP: 878565760
10 ------------------------------------
11 """
12
13
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装饰器来访问类的属性


复制代码
 1 """
 2 ------------------------------------
 3 @Time : 2019/7/4 20:57
 4 @Auth : linux超
 5 @File : python_property.py
 6 @IDE  : PyCharm
 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
 8 @QQ  : 28174043@qq.com
 9 @GROUP: 878565760
10 ------------------------------------
11 """
12
13
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修改的方法名字必须保持一致

linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款