You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@property与@setter获取类私有属性是否合理?还有哪些方法?

使用@property操作私有属性的合理性及其他属性访问方法

一、你的@property实现完全合理

你用@property和@name.setter操作私有属性__name的写法是非常规范的Python封装实现,合理性体现在这几点:

  • 数据合法性校验:setter里判断输入是否为非空字符串,能避免非法值被赋值给私有属性,这是直接暴露属性做不到的。
  • 封装性与接口统一:外部代码用os.name这种直观的属性语法访问,不用调用get_name()/set_name()这类方法,既保留了私有属性的封装性,又让调用体验更自然。
  • 可扩展性强:以后如果要给属性访问加日志、缓存,或者修改校验逻辑,只需要修改getter/setter的实现,外部调用代码完全不用改。

你的代码运行后,设置os.name = 'Elizabeth'会触发setter的校验(符合条件就修改__name),获取os.name会触发getter的日志打印,完全符合预期。

二、访问私有/保护属性的其他方法

Python里的私有属性(__开头)和保护属性(_开头)有不同的访问方式,除了@property,还有这些方法:

1. 直接访问保护属性(_开头)

保护属性是Python社区的约定俗成,没有强制的访问限制,外部可以直接通过对象._属性名访问或修改:

# 示例(假设类中定义的是保护属性_surname)
os = Person('Alexandra', 'Houston')
print(os._surname)
os._surname = 'Clark'

2. 访问名称修饰后的私有属性

Python会对__开头的私有属性做名称修饰,把__name变成_Person__name(格式为_类名__属性名),所以可以直接通过这个修饰后的名称访问:

os = Person('Alexandra', 'Houston')
print(os._Person__name)  # 直接获取私有属性
os._Person__name = 'Anna'  # 直接修改私有属性
os.show()  # 会打印Miss: Anna Houston

但这种方法非常不推荐,因为破坏了类的封装性,一旦类名修改,这个写法就会失效,而且绕过了类的校验逻辑。

3. 普通的get/set方法

不用@property,直接定义普通方法来获取和修改属性:

class Person:
    def __init__(self, name, surname):
        self.__name = name
        self.__surname = surname
    
    def get_name(self):
        print("Retrieving private attribute")
        return self.__name
    
    def set_name(self, m):
        if isinstance(m, str) and len(m) > 0:
            self.__name = m
        else:
            print("Error: Must be a non-empty string!")

os = Person('Alexandra', 'Houston')
os.set_name('Elizabeth')
print(os.get_name())

这种方法也能实现封装,但调用时需要用函数调用的语法,不如@property的属性式写法简洁。

4. 使用vars()函数

vars()函数可以获取对象的属性字典,通过字典键访问修饰后的私有属性:

os = Person('Alexandra', 'Houston')
print(vars(os)['_Person__name'])  # 获取私有属性
vars(os)['_Person__name'] = 'Carol'  # 修改私有属性

本质和直接访问修饰后的属性一样,同样不推荐使用。


内容的提问来源于stack exchange,提问作者aleksandrapacia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 19:13:10