当前位置: 首页 > article >正文

Python 中的函数装饰器:理解 @property、Getter 和 Setter 方法

封装和私有变量的重要性
封装的核心在于数据隐藏的思想——控制对对象内部状态的访问以防止意外干扰或误用。这需要使用私有变量。在许多编程语言中,私有变量用于确保对象内的敏感数据在未经适当授权的情况下无法直接访问或修改,从而保留给定对象的完整性。
python 不像其他一些语言那样具有严格的私有变量,而是使用在属性前添加单下划线 () 或双下划线 (_) 的约定,以表明它供内部使用。让我们来分解一下这两个约定之间的区别。

python 中的单下划线 (_) 与双下划线 (__)

a. 单下划线 (_):

变量开头的单个下划线(例如 _price)是一种约定,用于指示该属性供内部使用。 python 并未严格强制执行该属性,这意味着该属性仍然可以从类外部访问(即,它不是私有的)。但是,它向其他开发人员发出信号,表明该属性受到“保护”,除非必要,否则不应直接访问。 例子:

class product:
    def __init__(self, price):
        self._price = price  # protected attribute (convention)

product = product(10)
print(product._price)  # accessing is possible, but discouraged

b. 双下划线 (__):

变量开头的双下划线(例如 __price)会触发名称修改。名称修改在内部更改属性的名称,以防止从类外部意外访问或修改。这使得该属性更难直接访问,尽管它仍然不是完全私有的 - python 在内部通过在属性前面加上 _classname 来重命名该属性,使其只能通过其损坏的名称(例如 _product__price)进行访问。 例子:

class product:
    def __init__(self, price):
        self.__price = price  # name-mangled attribute

product = product(10)
# print(product.__price)  # this will raise an attributeerror
print(product._product__price)  # accessing the mangled attribute

当您想要避免意外覆盖子类中的属性或想要针对意外的外部访问提供更强的保护时,它们非常有用。
为什么使用私有属性?
私有属性,尤其是那些用单下划线 (_) 表示的属性,对于维护封装非常重要。它们通过阻止外部代码直接与对象交互来保护对象的内部状态,这有助于:

保持数据完整性:私有属性可防止敏感或关键内部数据的意外修改。
启用受控访问:通过使用 getter 和 setter 方法(或 @property 装饰器),对象控制如何以及何时访问或修改其属性,通常添加验证逻辑。
提高可维护性:由于隐藏了内部细节,您可以修改底层实现而不影响类的外部行为。
传统的 getter 和 setter 方法
在许多编程语言中,getter 和 setter 用于提供对私有变量的受控访问。请参阅下面的示例:

class product:
    def __init__(self, price):
        self._price = price  # protected attribute

    def get_price(self):
        return self._price

    def set_price(self, value):
        if value >= 0:
            self._price = value
        else:
            raise valueerror("price cannot be negative")

product = product(10)
print(product.get_price())  # 10
product.set_price(20)
print(product.get_price())  # 20

在此示例中,getter (get_price()) 和 set_price()) 提供了一种访问和修改 _price 属性的方法,同时执行某些规则(例如确保价格不为负)。

@property 装饰器
python 使用 @property 装饰器提供了一种更优雅的方式来管理对私有属性的访问。这个装饰器允许您定义行为类似于属性的方法,使代码更具可读性和python风格,同时仍然允许受控访问。

使用 @property 装饰器进行 getter 和 setter
下面是使用 @property 重构的前面的示例,以简化语法并提高可读性:

class Product:
    def __init__(self, price):
        self._price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value >= 0:
            self._price = value
        else:
            raise ValueError("Price cannot be negative")

product = Product(10)
print(product.price)  # 10
product.price = 20
print(product.price)  # 20

在此重构版本中:

@property装饰器允许我们像属性一样访问price(),即product.price,而不必调用像product.get_price()这样的getter方法。

@price.setter 装饰器启用设置价格值的逻辑,允许我们将其设置为 product.price = 20,同时仍然执行验证规则。

为什么使用@property?
@property 装饰器使您的代码更干净且更易于使用,特别是在处理私有属性时。原因如下:

可读性:它允许自然地访问属性,同时隐藏验证或转换的底层逻辑。
封装:您可以强制执行如何访问或修改属性的规则,而无需暴露内部实现细节。
灵活性:您可以在不更改外部接口的情况下重构内部行为,这意味着代码库的其余部分不会受到影响。


http://www.kler.cn/news/316907.html

相关文章:

  • (算法)大数的进制转换
  • ESP32-WROOM-32 [创建AP站点-客户端-TCP透传]
  • PostgreSQL中的regexp_split_to_table函数详解,拆分字段为多行
  • C++之STL—vector容器进阶篇
  • C++ STL全面解析:六大核心组件之一----序列式容器(vector和List)(STL进阶学习)
  • H5网页嵌在APP内部 手机锁屏后再打开 setInterval会重复执行
  • 【Git原理与使用】版本管理与分支管理(1)
  • LIN总线CAPL函数—— 设置报头同步间隔场长度(linSetBreakLength)
  • Redis数据结构之list列表
  • 116页可编辑PPT全面了解数据治理体系、平台,数据质量数据标准
  • Algo-Lab 2 Stack Queue ADT
  • 重修设计模式-设计原则
  • 图像生成大模型imagen
  • 【STM32 Blue Pill编程】-SPI主机和从机通信(两个STM32之间SPI通信)
  • Git使用详解:从安装到精通
  • 文件服务器FastDFS 消息队列中间件RabbitMQ
  • 快手IP归属地怎么设置别的地方
  • 【栅格地图实现布氏单元分解算法+栅格地图实现牛耕】Boustrophedon Cellular Decomposition Path Planning
  • WINDOWS AGENTARENA:EVALUATING MULTI-MODAL OS AGENTS AT SCALE论文学习
  • C++第六节课 - 拷贝构造函数
  • go语言 数组和切片
  • vue 页面常用图表框架
  • C++ std::find函数 容器元素查找
  • 机器学习-梯度下降实验一
  • 探索味蕾新境界,品味嘴尚绝卤味的健康之旅
  • 摩尔-彭罗斯伪逆(pinv)
  • spring 的启动过程
  • Kotlin 智能类型转换与 when 表达式(八)
  • 828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Redis集群
  • 实战19-详情页UI4等分