python使用property完成数据隐藏封装与校验
禁止随意设置属性需求
考虑这样一种情况,在某一个类中,有一个属性我们不希望别人随便设置,因为这可能会造成很大的麻烦:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height
r = Rectangle(3, 4)
print(r.calculate_area())在这种情况下,长度和宽度都应该是数字类型的,而如果有人在这个过程中修改了这个属性,那么就会导致错误。
r = Rectangle(3, 4)
r.width = "3"
print(r.calculate_area())# 结果为3333,明显不是我们希望的结果
私有属性
为了避免他人随意访问,我们可以将其设置为私有属性,通常可以添加1个或者2个下划线。
class Rectangle:
def __init__(self, width, height):
# 一个下划线通常表明了,这个属性不应该随意使用,但是不起实际作用
self._width = width
# 两个下划线表明了,这个属性会触发名称重整,但是也并非真正的私有
self.__height = height
r = Rectangle(3, 4)
print(r._width)
# 双下划线最终会重整为_类名__属性名的形式
print(r._Rectangle__height)需要注意的是,由于python中没有真正的私有属性,所以,这两种设置方法都不能完全起到作用,但是一般而言,两个下划线是更好的,因为可以触发名称重整。
提供访问方法
在这种情况下,为了避免他人随意设置属性,因此需要提供专门的访问方法。
class Rectangle:
def __init__(self, width, height):
self.set_width(width)
self.set_height(height)
def set_width(self, width):
if not isinstance(width, (int, float)):
raise ValueError("width must be a number.")
if width <= 0:
raise ValueError("width must be greater than 0.")
self.__width = width
def set_height(self, height):
if not isinstance(height, (int, float)):
raise ValueError("height must be a number.")
if height <= 0:
raise ValueError("height must be greater than 0.")
self.__height = height
def get_width(self):
return self.__width
def get_height(self):
return self.__height
r = Rectangle(3, 4)
# 此时需要通过专门的方法进行访问
print(r.get_width())
# 非法的设置不再被允许
r.set_width("3")但是这样的使用方法并不方便,因此,在python中,一个更好的使用方法是通过property。
property的详细介绍
基本语法
基本语法实现是通过property的内置函数完成的
class MyClass:
def __init__(self, value):
self.value = value
# get方法
def get_value(self):
return self.__value
# set方法
def set_value(self, value):
if value < 0:
raise ValueError("value must be non-negative.")
self.__value = value
# del方法
def del_value(self):
print("value is being deleted.")
del self.__value
# property创建
value = property(get_value, set_value, del_value)
mc = MyClass(20241120)
print(mc.value)
使用装饰器
class MyClass:
def __init__(self, value):
self.value = value
@property
def value(self):
return self.__value
@value.setter
def value(self, value):
if value < 0:
raise ValueError("value must be non-negative.")
self.__value = value
@value.deleter
def value(self):
print("value is being deleted.")
del self.__value与基本语法的版本效果是相同的
常见应用
数据隐藏与封装
property装饰器允许像访问和操作普通一样属性进行操作
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):
if not isinstance(value, (int, float)):
raise ValueError("width must be a number.")
if value <= 0:
raise ValueError("width must be greater than 0.")
self.__width = value
@property
def height(self):
return self.__height
@height.setter
def height(self, value):
if not isinstance(value, (int, float)):
raise ValueError("height must be a number.")
if value <= 0:
raise ValueError("height must be greater than 0.")
self.__height = value
r = Rectangle(3, 4)
print(r.width)
r.width = "3"
设置只读属性
通过property,可以设置一个属性只允许读取,不允许修改
class Person:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
# 初始化的时候可以设置名字
p = Person("sagegrass")
# 名字可以正常被访问
print(p.name)
# 名字不可以被修改,AttributeError: can't set attribute 'name'
p.name = "xxx"一般来说,这样设置已经足够保证属性只读,但是极特殊的情况下,仍然可以通过p._Person__name进行修改,
不过通常无需额外关注这一问题。
动态计算
关于一开始的例子,我们使用calculate_area进行面积的计算,但是,通过property就可以将area设置为一个属性,进行动态的计算
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height使用property属性,修改为:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height
r = Rectangle(3, 4)
print(r.area)
r.width = 5
print(r.area)以上就是python使用property完成数据隐藏封装与校验的详细内容,更多关于python property数据隐藏封装与校验的资料请关注脚本之家其它相关文章!
来源:https://www.jb51.net/python/331172mmq.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页:
[1]