1. 什么是property属性
在Python中,property是一种特殊的装饰器,可以将类中的方法像属性一样使用。它可以将一个方法转换为类的一个属性,当属性被调用时,该方法会自动执行,返回值就是该属性的值。
在Python的面向对象编程中,使用property属性与直接定义属性相比,可以更加灵活地控制属性的赋值和取值。通过property属性,我们可以设置属性的只读、只写、可读可写等权限,以及进行数据的类型检查和限制,确保属性值的有效性。
2. 创建property属性
要创建property属性,我们需要使用Python自带的property装饰器。在使用property装饰器之前,我们先来看一个案例,了解为什么需要使用property。
2.1 案例:不使用property的情况
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
c = Circle(5)
print(c.radius) # 5
print(c.area()) # 78.5
在上面的代码中,我们创建了一个圆形对象,该对象的属性为半径,方法为计算圆形的面积。我们可以通过直接访问半径属性,并调用area方法计算面积。
但是,如果我们希望修改该圆形对象的半径,我们只能通过直接修改半径属性的方式实现:
c.radius = 10
print(c.radius) # 10
print(c.area()) # 314.0
虽然这种方式看起来简单,但是存在如下问题:
属性没有被有效的封装
可能会有人不知道该如何修改属性
属性修改时无法进行数据的有效性检查和限制
接下来,我们将使用property属性重新定义Circle类:
2.2 使用property的情况
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError('半径必须大于0')
else:
self._radius = value
def area(self):
return 3.14 * self.radius ** 2
c = Circle(5)
print(c.radius) # 5
print(c.area()) # 78.5
c.radius = 10
print(c.radius) # 10
print(c.area()) # 314.0
在上面的代码中,我们通过使用@property装饰器,将radius方法转换为属性,可以像直接访问属性一样访问和修改半径属性。
同时,我们还定义了一个setter方法,确保半径属性的有效性。当半径值小于等于0时,程序将抛出一个ValueError异常。
3. property属性的应用场景
property属性常用于以下场景:
3.1 控制属性的只读或只写权限
class Student:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
s = Student('小明', 18)
print(s.name) # 小明
# 下面这行代码会抛出AttributeError异常
# s.name = '张三'
在上面的代码中,我们使用@property装饰器,将name和age方法转换为只读属性,修改属性将抛出AttributeError异常。
3.2 控制属性的读写权限
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
@property
def width(self):
return self._width
@width.setter
def width(self, value):
self._width = value
@property
def height(self):
return self._height
@height.setter
def heigh(self, value):
self._height = value
r = Rectangle(10, 20)
print(r.width) # 10
# 可以修改width属性
r.width = 30
print(r.width) # 30
# 下面这行代码会抛出异常
# r.height = 30
在上面的代码中,我们使用@property装饰器,将width和height方法转换为可读可写属性,read-write属性。
同时,我们还定义了setter方法,确保属性值的有效性。
3.3 控制属性的类型
class Dog:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if isinstance(value, int) and value >= 0:
self._age = value
else:
raise ValueError('年龄必须为非负整数')
d = Dog('旺财', 2)
print(d.age) # 2
# 下面这行代码会抛出ValueError异常
# d.age = -1
在上面的代码中,我们通过定义setter方法,控制了age属性的类型和范围,确保属性值的有效性。
4. 总结
在Python中,使用property属性可以将类中的方法像属性一样使用。它可以将一个方法转换为类的一个属性,当属性被调用时,该方法会自动执行,返回值就是该属性的值。
通过property属性,我们可以更加灵活地控制属性的赋值和取值。通过setter方法,我们可以对属性值进行有效性检查和限制,确保属性值的有效性。
最后,通过合理的使用property属性,可以使我们的面向对象程序更加健壮和易于维护。