1. 什么是python property?
property是一个由Python提供的内置函数,用于将获取属性值的方法与设置属性值的方法明确地分离开来,以便以后对这些方法进行扩展或修改的能力。
1.1 用处
在实际开发中,经常会遇到需要对属性值进行额外操作或判断的情况,比如限定属性值的范围、或让属性只读、或实现对属性的加密处理等。这时,就可以使用property函数,来将属性的读写操作进行分类,从而实现更加灵活的编程。
1.2 定义
使用property函数定义属性时,需要定义getter方法和setter方法(可选),如下所示:
class Demo:
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
在上面的代码中,Demo类含有一个名为x的属性,它由getter方法(x方法)和setter方法(x方法的装饰器中定义)共同管理。其中,getter方法用于获取属性值,setter方法用于设置属性值。此外,Demo类的x属性前面使用了@property装饰器,这是使用property函数定义属性必须的步骤,它将x方法转变为一个只读属性。
2. python property的应用场景
property函数广泛应用于Python的类中,主要用于定义属性。下面是该函数的一些典型应用场景。
2.1 计算属性
计算属性指的是那些不是直接从实例的__dict__字典中获取的属性,而是通过一系列逻辑操作得到的属性。通过定义getter方法,可以将这样的属性封装成属性调用。比如下面的代码演示了如何在Python中定义一个计算属性:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def diameter(self):
return self.radius * 2
在这个示例中,Circle类含有一个名为diameter的属性,它是通过getter方法获取半径radius的值,并将其乘以2计算得到的。由于diameter方法前面加了@property装饰器,所以它会将方法封装成一个只读属性,当属性被访问时,会自动调用getter方法并返回其结果。
2.2 只读属性
只读属性指的是那些只能读取,而不能写入的属性。在Python中,可以通过将属性的setter方法设置成一个错误方法,来实现只读属性。例如下面的代码演示了如何在Python中实现一个只读属性:
```
class Demo:
def __init__(self):
self._x = None
@property
def x(self):
return self._x
@x.setter
def x(self, value):
raise AttributeError("can't set attribute")
d = Demo()
d.x = 10 # 报错,只读属性不能进行赋值操作
```
在上面的代码中,定义了一个名为x的只读属性,由于它的setter方法抛出了一个AttributeError异常,所以在进行写入(赋值)操作时,会抛出一个错误。
2.3 属性限制
属性限制指的是那些需要对属性值进行额外限制或检查的属性,比如限制属性值的范围、或实现对属性的加密处理等。通过在setter方法中,进行额外的属性检查或处理,可以实现属性限制功能。比如下面的代码演示了如何在Python中实现一个属性限制:
class Demo:
def __init__(self, value):
self._x = value
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if value < 0 or value > 100:
raise ValueError('value out of range')
self._x = value
d = Demo(50)
d.x = 200 # 报错,属性值超出了预设范围
在上面的代码中,定义了一个名为x的属性,它的取值范围是[0, 100]。在setter方法中,对属性值进行了检查,如果不在预设的范围内,就会抛出一个ValueError异常。
3. python property的优点
采用使用property函数的方式,具有以下几个优点:
3.1 对属性的操作更加灵活
使用property函数可以将一个“属性”拆分成“获取”和“设置”两个操作,可以给属性的读写操作赋予更多的含义。同时,还可以动态的修改getter和setter方法,从而使得整个系统更有弹性。
3.2 提高代码的复用度
当我们没有使用property函数的时候,在属性获取和属性设置方法中通常需要写入相同的代码来处理属性的读写操作,而通过使用property函数,这些代码可以在一个方法中统一管理起来,从而大大提高了代码的复用度。
3.3 增加代码的可读性
通过将属性的获取方法和设置方法放置在一起,使用者可以更加清晰地看到属性的读写操作,并且不容易将其与其他逻辑混淆。同时,property函数的使用也避免了代码中出现大量的判断语句,让代码更加易读易懂。
4. python property的缺点
尽管python property函数有很多优点,但实际开发中也存在一些需要注意的问题。主要有以下几个方面:
4.1 执行效率较低
由于使用property函数需要通过方法的调用方式实现值的读取和写入,所以其执行效率会比直接对__dict__字典进行读写略低。因此,在对性能要求比较高的情况下,应该尽量避免使用property函数。
4.2 无法使用容器类型进行批量操作
由于是通过方法进行读写操作的,所以无法像直接对属性进行读写操作一样,使用list、dict等容器类型进行批量操作。
5. 编程实例
我们可以通过一个类TemperatureConverter来演示属性getter和setter的使用。
class TemperatureConverter:
def __init__(self, temperature=0):
self._celsius = temperature
def fahrenheit(self):
return (self._celsius * 1.8) + 32
def kelvin(self):
return self._celsius + 273.15
def get_temperature(self, unit="c"):
if unit.lower() == "c":
return self._celsius
elif unit.lower() == "k":
return self.kelvin()
elif unit.lower() == "f":
return self.fahrenheit()
else:
raise ValueError("Invalid unit value.")
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
self._celsius = value
5.1 实例化对象
tc = TemperatureConverter()
5.2 获取属性值和温度转换
# 获取属性值
celsius_0 = tc.celsius
print("celsius_0: ", celsius_0)
# 设置属性值
tc.celsius = 20
# 获取属性值
celsius_1 = tc.get_temperature()
kelvin_1 = tc.get_temperature('k')
fahrenheit_1 = tc.get_temperature('f')
print("celsius_1: ", celsius_1)
print("kelvin_1: ", kelvin_1)
print("fahrenheit_1: ", fahrenheit_1)
运行结果如图所示:
![property实例运行结果](https://cdn.luogu.com.cn/upload/image_hosting/srfaimlc.png)
总结
Python property函数是一个非常有用的函数,它可以让我们更加灵活地进行属性的读写操作,同时也使得代码的复用性和可读性有所提升。需要注意的是,由于property函数的getter和setter方法都是方法调用,所以其性能不如直接对属性进行读写。另外,由于无法使用容器类型进行批量操作,所以在涉及到多个属性同时操作时,也需要进行注意。