Python 中的属性方法@property 介绍

1. 类属性和实例属性

Python中类和实例都是对象, 可以在定义时或者通过 . 语法设置和读取属性内容. 

In [1]: class Demo:
   ...:     cls_name = "Demo"
   ...:     def __init__(self, name):
   ...:         self.name = name
In [2]: demo = Demo('demo')

In [3]: demo.name
Out[3]: 'demo'
In [4]: demo.cls_name
Out[4]: 'Demo'
In [5]: Demo.cls_name
Out[5]: 'Demo'

In [6]: Demo.cls_name = 'New Class Name'
In [7]: demo.cls_name
Out[7]: 'New Class Name'

In [8]: demo.cls_name = 'Custom Name'
In [9]: demo.cls_name
Out[9]: 'Custom Name'

上面的代码示例, 先定义了一个Demo类, 包含一个类属性cls_name, __init__方法中初始化实例的时候, 定义了实例属性name. 

demo是Demo类的一个实例, 可以看到通过demo可以访问实例属性name='demo', 当在实例中获取不到一个属性的值的时候, 会尝试去父类中获取, 类似"子债父偿"的概念, 直到所有父类中都不存在, 抛出AttributeError.

如果类属性修改, 则实例中获取到的值, 也会变化. 

2. 实例属性的缺陷

直接把变量暴露出去, 好处是便于修改, 写起来方便.  随之而来的缺陷是, 可以被随意修改, 无法做参数检查,和一下动态的属性. 如下例, 

In [1]: class Square:
   ...:     def __init__(self, side):
   ...:         self.side = side
   ...:         self.area = side * side
In [2]: squ = Square(5)

In [3]: squ.side
Out[3]: 5
In [4]: squ.area
Out[4]: 25

定义一个正方形类, 有两个属性边长和面积. 对边长属性可以被置成负数显然是不可理的

In [5]: squ.side=-90

一个解决方法是, 通过添加方法set_side()来实现参数的校验. 

In [1]: class Demo:
   ...:     def __init__(self, side):
   ...:         self._side = side
   ...:     def set_side(self, length):
   ...:         self._side = max(length, 0)
   ...:     def get_side(self, length):
   ...:         return self._side 
   ...:     def get_area(self):
   ...:         return self._side * self._side

In [2]: demo = Demo(6)
In [3]: demo.get_area()
Out[3]: 36

In [4]: demo.set_side(-9)
In [5]: demo.get_side()
Out[5]: 0

这样写虽然实现了参数校验的功能, 需要调用函数来set_side设置和get_side返回属性的值, 调用起来复杂, 可读性来说也不是很友好.

3. 使用@property

@property装饰器会将方法转换为相同名称的属性, 使得你可以用获取属性的方式来调用方法. 

In [1]: class Demo:
   ...:     def __init__(self, side):
   ...:         self._side = side
   ...:     @property
   ...:     def side(self):
   ...:         return self._side
In [2]: demo =Demo(3)

In [3]: demo.side
Out[3]: 3
In [3]: demo.side = 90
AttributeError: can't set attribute

通过装饰器@property装饰了的side方法, 当执行demo.side的访问side属性时候,实际执行的是side()方法, side是只读属性, 尝试赋值的时候, 会报 AttributeError. 如果要对property赋值, 需要实现一个attr.setter的方法, 本例中attr就是side.

In [1]: class Demo:
   ...:     def __init__(self, side):
   ...:         self._side = side
   ...:     @property
   ...:     def side(self):
   ...:         return self._side
   ...:     @side.setter
   ...:     def side(self, value):
   ...:         self._side = max(value, 0)
   ...:     @property
   ...:     def area(self):
   ...:         return self._side * self._side

In [2]: demo = Demo(5)
In [3]: demo.area
Out[3]: 25

In [4]: demo.side = -8
In [5]: demo.side
Out[5]: 0
In [6]: demo.area
Out[6]: 0

总结

使用@property, 可以把一个方法变成属性调用, 这样

① 可以在属性的赋值和获取的时候添加例如格式校验等额外功能,

② 提供更加直观, 调用友好的代码.

使用方式:

@property装饰器实现属性的获取,  属性名.setter实现属性的赋值, 属性名.delete 实现属性的删除.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
装饰器(decorator)是一种可以给函数或类动态添加功能的工具。在Python,有一些内置的装饰器,比如@staticmethod、@classmethod和@property。 @staticmethod装饰器用于定义静态方法。静态方法是一个和类没有绑定关系的方法,可以直接通过类名调用,也可以通过实例调用。使用@staticmethod装饰器可以将一个方法转变为静态方法。 @classmethod装饰器用于定义类方法。类方法是与类相关联的方法,通过类名调用时,会将类本身作为第一个参数传入。使用@classmethod装饰器可以将一个方法转变为类方法@property装饰器用于定义属性属性是一种特殊的方法,可以像访问属性一样来访问方法。使用@property装饰器可以将一个方法转变为属性。通常,一个@property装饰器会配合一个相应的.setter装饰器使用,来定义属性的设置方法。 举个例子,对于一个名为Student的类: class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value 这个类的score方法@property装饰器修饰,使得它可以像属性一样被访问。同时,@score.setter装饰器定义了一个setter方法,用于设置score属性的值。这样,我们可以通过实例的score属性来获取和设置学生的成绩。 总结起来,@staticmethod、@classmethod和@propertyPython内置的装饰器,分别用于定义静态方法、类方法属性。它们可以让我们的代码更加简洁和易读。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python面试常问的几个内置装饰器:@staticmethod、@classmethod和@property](https://blog.csdn.net/weixin_35383324/article/details/113674252)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python 使用@property属性进行数据规范性校验](https://blog.csdn.net/a772304419/article/details/120813610)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值