python使用property完成数据隐藏封装与校验

 更新时间:2024年11月22日 09:16:54   作者:仙草哥哥  
这篇文章主要为大家详细介绍了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数据隐藏封装与校验的资料请关注脚本之家其它相关文章!

相关文章

  • Python3.7 读取音频根据文件名生成脚本的代码

    Python3.7 读取音频根据文件名生成脚本的代码

    这篇文章主要介绍了Python3.7 读取音频根据文件名生成字幕脚本的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • python使用正则表达式的search()函数实现指定位置搜索功能

    python使用正则表达式的search()函数实现指定位置搜索功能

    SEARCH函数,函数名。主要用来返回指定的字符串在原始字符串中首次出现的位置 ,从左到右查找,忽略英文字母的大小写。接下来通过本文给大家介绍python使用正则表达式的search()函数实现指定位置搜索功能,需要的朋友一起看看吧
    2017-11-11
  • Python实现删除列表首元素的多种方式总结

    Python实现删除列表首元素的多种方式总结

    在Python中,处理列表的操作是日常开发中不可避免的任务之一,其中,删除列表中的元素是一个常见的需求,本文为大家整理了Python中删除列表中的第一个元素的多种方法,需要的可以参考下
    2023-12-12
  • python动态参数用法实例分析

    python动态参数用法实例分析

    这篇文章主要介绍了python动态参数用法,以实例形式较为详细的分析了Python中动态参数的功能及使用技巧,需要的朋友可以参考下
    2015-05-05
  • python网络爬虫精解之pyquery的使用说明

    python网络爬虫精解之pyquery的使用说明

    PyQuery是一个类似于jQuery的解析网页工具,使用lxml操作xml和html文档,它的语法和jQuery很像。和XPATH,Beautiful Soup比起来,PyQuery更加灵活,提供增加节点的class信息,移除某个节点,提取文本信息等功能
    2021-09-09
  • Tornado Web服务器多进程启动的2个方法

    Tornado Web服务器多进程启动的2个方法

    这篇文章主要介绍了Tornado Web服务器多进程启动的2个方法,Tornado是一个用Ptyhon写的WEB服务器,需要的朋友可以参考下
    2014-08-08
  • python tkinter自定义实现Expander控件

    python tkinter自定义实现Expander控件

    和其他成熟的GUI库相比,tkinter的组件并不是太多,但在自定义组件这一点上,并不逊色于其他框架,下面小编就教大家如何自定义一个Expander控件吧
    2023-08-08
  • Python日志模块Logging使用指北(最新推荐)

    Python日志模块Logging使用指北(最新推荐)

    Logging模块是Python中一个很重要的日志模块,它提供了灵活的日志记录功能,广泛应用于调试、运行状态监控、错误追踪以及系统运维中,这篇文章主要介绍了Python日志模块Logging使用指北,需要的朋友可以参考下
    2025-04-04
  • Python序列循环移位的3种方法推荐

    Python序列循环移位的3种方法推荐

    下面小编就为大家分享一篇Python序列循环移位的3种方法推荐,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-04-04
  • Pytorch 如何实现LSTM时间序列预测

    Pytorch 如何实现LSTM时间序列预测

    本文主要基于Pytorch深度学习框架,实现LSTM神经网络模型,用于时间序列的预测
    2021-05-05

最新评论