脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - python @property 装饰器使用方法

python @property 装饰器使用方法

2022-11-12 10:22周兵 Python

这篇文章主要介绍了python @property 装饰器使用详细,使用property可以讲类的方法变成同名属性,使用起来更加简洁,下文最后举例说明详情说明需要的小伙伴可以参考一下

一、property的装饰器用法

先简单上个小栗子说明:

class property(fget=None,fset=None,fdel=None,doc=None)

  • fget是用于获取属性值的函数
  • fset是用于设置属性值的函数
  • fdel是用于删除属性值的函数
  • doc为属性对象创建文档字符串

使用property可以讲类的方法变成同名属性,使用起来更加简洁,最后实例展示

使用时建议直接用property的装饰器用法, 比较简洁,下面是官方示例,利用@property装饰方法x将其变成名称相同的属性, 通过fget, fset, fdel可以控制x的读写删属性.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class C:
    def __init__(self):
        self._x = None
 
    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x
 
    #设置fset,注意x要与@property修饰的方法名称相同
    @x.setter
    #这个fset名称没有限制,建议与x相同
    def x(self, value):
        self._x = value
 
    #设置fdel
    @x.deleter
    def x(self):
        del self._x

话不多说, 直接上例子, 在Man这个类中设置一个可读可写的birthYear属性,一个可读gender属性,一个可读可写可删的体重属性,还有一个利用birthYear推算出的age属性

?
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
""" @property, @*.setter"""
from datetime import datetime
 
class Man:
    def __init__(self, birthYear=None, gender=None, weight=None):
        """1.使用@property可以隐藏私有属性,例如把'_birthYear'属性隐藏,
             把property对象birthYear作为对外的属性"""
 
        self._birthYear = birthYear
        self._gender = gender
        self._weight = weight
 
    @property
    def birthYear(self):
        return self._birthYear
    
    @birthYear.setter
    def birthYear(self, value):
       """2.可以在setter中对属性输入进行限制或者其他操作"""
        assert not value > datetime.now().year, f'please input the right value!'
        self._birthYear = value
 
    @property
    """3.获取年龄直接用obj.age,而不需写成方法obj.age(), 更加自然方便"""
    def age(self):
        return datetime.now().year - self._birthYear
 
    @property
    def gender(self):
        return self._gender
 
    @property
    def weight(self):
        return self._weight
    
    @weight.setter
    def weight(self, value):
        self._weight = value
 
    @weight.deleter
    def weight(self):
        del self._weight
 
lilei = Man(1996, 'male', 180)
age = lilei.age
print('Lilei今年{}岁\n'.format(age))
 
# 设置性别
try:
    lilei.gender = 'female'
except:
    print('性别无法进行更改!\n')
 
# 更新体重
print(f'lilei减肥前的体重:{lilei.weight}\n')
lilei.weight = 200
print(f'lilei减肥后的体重:{lilei.weight}\n')
print('lilei减肥失败后一气之下将体重信息删了\n')
del lilei.weight
try:
    print('lilei的体重{}'.format(lilei.weight))
except:
    print('找不到lilei的体重信息!')

输出结果:

Lilei今年25岁

性别无法进行更改!

lilei减肥前的体重:180

lilei减肥后的体重:200

lilei减肥失败后一气之下将体重信息删了

找不到lilei的体重信息!

二、举例说明

现在让我们直观看一下python内置property修饰器为什么会存在,可以用来解决什么问题?

先来一个具体的例子,定义一个表示摄氏度的class并且这个类包含一个从摄氏度转换到华氏温度的方法。

1.不用setter和getter方法的实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 初始版本
class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature
 
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
 
# 实例化
human = Celsius()
# 设置温度
human.temperature = 37
# 获取温度值
print(human.temperature)
# 调用内置方法将摄氏度转化为华氏温度
print(human.to_fahrenheit())

输出结果:

37
98.60000000000001

2.使用setter和getter的实现,增加温度值输入的限制

但是如果现在有人让human.temperature = -300 , 我们知道摄氏温度是不可能低于-273.15的,此时需要对温度值进行限制, 常规方法是设置一个温度值的settergetter的方法,此时温度值存放在_temperature 中

?
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
# 更新温度限制的版本
class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)
 
    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32
 
    # getter method
    def get_temperature(self):
        return self._temperature
 
    # setter method
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("摄氏温度不可能低于 -273.15 !")
        self._temperature = value
 
# 实例化
human = Celsius(37)
 
# 使用添加的getter获取温度值
print(human.get_temperature())
 
# 调用内置方法将摄氏度转化为华氏温度
print(human.to_fahrenheit())
 
# 使用添加的setter对温度值进行设置
human.set_temperature(-300)
 
# Get the to_fahreheit method
print(human.to_fahrenheit())

毫无疑问,在设置温度值等于-300的时候肯定会报错,但是这个时候你可能发现设置和获取温度值的代码发生变化而且更复杂 并且 你需要对Celsius类的初始化函数进行更改,self.temperature = temperature self.set_temperature(temperature), 如果现在是一个拥有很多属性的类, 一个一个去进行这样的更改是很麻烦的,而且可能会导致与这个类别相关的代码出现错误, 有没有更好的实现方式呢?这个时候就该今天的主角property装饰器出场了

3.利用property装饰器实现的版本

?
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
# 使用 @property 装饰器版本
class Celsius:
    def __init__(self, temperature=0):
        #这里的self.temperture是下面定义的property对线 temperatue
        #所以你会发现在初始化Celsius时, 调用了temperature.setting方法
        self.temperature = temperature
 
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
 
    @property
    def temperature(self):
        print("获取温度值...")
        return self._temperature
 
    @temperature.setter
    def temperature(self, value):
        print("设置温度值...")
        if value < -273.15:
           raise ValueError("摄氏温度不可能低于 -273.15 !")
        self._temperature = value
 
 
# 用property的实现后获取和设置温度值与最初的版本一样!
human = Celsius()
# 设置温度
human.temperature = 37
# 获取温度值
print(human.temperature)
# 调用内置方法将摄氏度转化为华氏温度
print(human.to_fahrenheit())
 
#测试温度限制功能
human.temperature = -300

输出结果:

设置温度值...
设置温度值...
获取温度值...
37
获取温度值...
98.60000000000001
设置温度值...
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
d:\2.github\python_demo\016_decorator.py in <module>
     30 
     31 #测试温度限制功能
---> 32 human.temperature = -300

d:\2.github\python_demo\016_decorator.py in temperature(self, value)
     16         print("设置温度值...")
     17         if value < -273.15:
---> 18            raise ValueError("摄氏温度不可能低于 -273.15 !")
     19         self._temperature = value
     20 

ValueError: 摄氏温度不可能低于 -273.15 !

可以看到此时temperature设置有限制而且获取和设置温度值的代码与初始版本一模一样,也就是说代码可以向后兼容

到此这篇关于python @property 装饰器使用详细的文章就介绍到这了,更多相关python @property 装饰器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://zhuanlan.zhihu.com/p/358361657

延伸 · 阅读

精彩推荐
  • Pythonpandas 对每一列数据进行标准化的方法

    pandas 对每一列数据进行标准化的方法

    今天小编就为大家分享一篇pandas 对每一列数据进行标准化的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    隔壁的老王12352021-03-03
  • Pythondjango session完成状态保持的方法

    django session完成状态保持的方法

    这篇文章主要介绍了django session完成状态保持的方法,使用登录页面演示session的状态保持功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    crystaleone7672021-04-22
  • PythonPython numpy 提取矩阵的某一行或某一列的实例

    Python numpy 提取矩阵的某一行或某一列的实例

    下面小编就为大家分享一篇Python numpy 提取矩阵的某一行或某一列的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    luoganttcc29942021-01-27
  • Pythonpython自动化测试工具Helium使用示例

    python自动化测试工具Helium使用示例

    大家好,本篇文章主要讲的是python自动化测试工具Helium使用示例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下哦...

    Python 集中营8122022-03-10
  • Pythonpython3+PyQt5泛型委托详解

    python3+PyQt5泛型委托详解

    这篇文章主要为大家详细介绍了python3+PyQt5泛型委托的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    basisworker5732021-02-05
  • PythonDjango Form设置文本框为readonly操作

    Django Form设置文本框为readonly操作

    这篇文章主要介绍了Django Form设置文本框为readonly操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    9393972327822020-07-04
  • Python使用实现XlsxWriter创建Excel文件并编辑

    使用实现XlsxWriter创建Excel文件并编辑

    今天小编就为大家分享一篇使用实现XlsxWriter创建Excel文件并编辑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    grey_csdn9052021-02-15
  • PythonPython中关键字global和nonlocal的区别详解

    Python中关键字global和nonlocal的区别详解

    这篇文章主要给大家介绍了关于Python中关键字global和nonlocal的区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考...

    一笑199010312021-03-31