关于Python私有属性与受保护属性的一点思考

Q:自定义的类是否可变?
A:这取决于类的设计,但是从技术上讲,Python中的类都是可变的

以下为两个例子

class MyMutableClass:

    def __init__(self, value):
        self.value = value

    def set_value(self, new_value):
        self.value = new_value  # 允许修改实例状态,因此是可变的


class MyImmutableClass:

    def __init__(self, value):
        self._value = value  # 使用单下划线前缀表示这一个“受保护”的属性,但Python中的受保护只是约定

    # 没有提供修改_value的方法,因此可以认为这个类是不可变的(尽管技术上可以通过其他方式修改)

    @property
    def value(self):
        return self._value


# 使用示例
mutable = MyMutableClass(10)
print(mutable.value)  # 10
mutable.set_value(20)  # 修改了mutable的状态
print(mutable.value)  # 20

immutable = MyImmutableClass(10)
print(immutable.value)  # 10
immutable._value= 20  # 这会违反类的封装原则,但技术上可行
print(immutable.value)  # 20

示例代码中,尽管用单下划线为前缀表示这是一个“受保护”属性,但这只是一种约定俗成,并没有语法层面的严格限制,类外部依然可以访问到。就如同全大写的变量视作常量一样。

如果用双下划线作为前缀呢?

# 双下划线开头的属性是私有属性,不应该被直接访问
class MyImmutableClass:

    def __init__(self, value):
        self.__value = value  # 使用双下划线前缀表示这一个“私有”的属性



    @property
    def value(self):
        return self.__value


immutable=MyImmutableClass(10)
print(immutable.value)  # 10
print(dir(immutable)) # 查看类的属性 没有__value
"""
['_MyImmutableClass__value', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'value']
"""
immutable.__value=20  # 直接修改__value属性,但实际上是创建了一个新的属性
print(immutable.value)  # 10 没有修改成功
immutable._MyImmutableClass__value=20  # 触发名称改写,通过这种方式修改私有属性
print(immutable.value)  # 20 修改成功

名称改写:在类定义中使用双下划线(__)作为属性名的前缀时,Python解释器会自动将这些属性名改写为一个包含类名前缀的新名称。
改写的规则是,在属性名前加上单下划线和类名。例如代码中的__value被改写成_MyImmutableClass__vlaue

从语法角度,严格限制外部访问类内部“私有”属性的规则并不存在。
类内部单下划线开头的,被约定为“受保护”属性,类外部可以通过
类内部双下划线开头的变量,类外部直接访问会触发“名称改写”,因此无法访问到,但如果知道改写后的名称,则可以正常访问。

参考:
https://docs.python.org/zh-cn/3/tutorial/classes.html#private-variables
https://docs.python.org/zh-cn/3/reference/expressions.html#private-name-mangling

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值