Python @property 装饰器原理与 Getter/Setter 实现详解
本文详解 Python 中 @property 装饰器的核心原理,展示如何将方法转换为属性访问以简化调用并防止直接修改。通过具体代码示例,深入解析如何利用 @property 结合 @score.setter 实现可控的读写属性,以及如何仅定义 getter 创建只读属性。同时指出了调用时常见的 TypeError 错误原因,帮助开发者规范类属性设计。
@property 装饰器的核心作用
@property 的主要作用在于优化类属性的访问方式。
在 Python 中,@property 是一种装饰器,专门用于修饰方法。
利用 @property 装饰器,我们可以创建只读属性。该装饰器会将原本的方法转换为同名的只读属性,并与已定义的属性配合使用,从而有效防止属性被意外修改。
方法修饰与访问方式
第一点:修饰方法,使其能够像普通属性一样被访问。
class DataSet(object):
@property
def method_with_property(self): ##含有@property
return 15
def method_without_property(self): ##不含@property
return 15
l = DataSet()
print(l.method_with_property) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
print(l.method_without_property()) #没有加@property , 必须使用正常的调用方法的形式,即在后面加()#两个都输出为15。
若在使用 @property 修饰后,调用时仍给方法添加括号 (),程序将报错:TypeError: 'int' object is not callable。这表明添加 @property 后,该方法已转变为属性,若再添加括号试图将其作为函数调用,会因对象不可调用而引发错误。
具体表现为,添加括号即视为函数调用,但此时它已不可调用(not callable)。
第二点:与已定义的属性配合使用,防止属性被修改。 由于 Python 在定义属性时无法直接设置私有属性,因此需要通过 @property 方法来实现这一功能。这种方式可以隐藏属性名,使用户在调用时无法随意修改,从而保护数据完整性。
class DataSet(object):
def __init__(self):
self._images = 1
self._labels = 2 #定义属性的名称
@property
def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
return self._images
@property
def labels(self):
return self._labels
l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
Getter 与 Setter 的实现机制
关于 getter 和 setter 方法的实现:
只需在 getter 方法上加上 @property,即可将其变为属性。此时,@property 本身又创建了另一个装饰器 @score.setter,负责将 setter 方法变为属性赋值操作。由此,我们拥有了一个可控的属性操作机制:
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
当我们在实例上操作属性时,可以意识到该属性可能并未直接暴露,而是通过 getter 和 setter 方法间接实现的。
此外,还可以定义只读属性:仅定义 getter 方法而不定义 setter 方法,即可构成只读属性:
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter #设置属性
def birth(self, value):
self._birth = value
@property
def age(self):
return 2015 - self._birth
上述代码中,birth 是可读写属性,而 age 则是只读属性,因为 age 的值是根据 birth 和当前时间计算得出的。
总结与应用建议
小结:
@property 广泛应用于类的定义中,它允许调用者编写简短的代码,同时确保对参数进行必要的检查。这样,在程序运行时减少了出错的可能性。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









