Python类与对象学习心得-3:类的访问控制

Python 程序员并不依赖语言特性去封装数据,而是通过遵循一定的属性和方法命名规范来达到这个效果。第一个约定是任何以单下划线 _ 开头的名字都应该被认定为内部实现。比如:

class A:
    def __init__(self):
        self._internal = 0 # 一个内部属性
        self.public = 1    # 一个公共属性

    def public_method(self):
        '''
        一个公共方法
        '''
        pass

    def _internal_method(self):
        pass

Python 没有语言机制去阻止别人访问内部名称。但是如果你这么做肯定是不好的,可能会导致脆弱的代码。同时还要注意到,使用下划线开头的约定同样适用于模块名和模块级别函数。例如,如果你看到某个模块名以单下划线开头(比如 _socket),那它就是内部实现。类似的,模块级别函数比如 sys._getframe() 在使用的时候就得特别小心了。

你还可能还会遇到在类定义中使用两个下划线(__) 开头的命名。比如:

class B:
    def __init__(self):
        self.__private = 0

    def __private_method(self):
        pass

    def public_method(self):
        self.__private_method()

命名时使用双下划线开始会导致访问名称变成其他形式(像 __init__() 那样以双下划线结尾的特殊方法除外)。比如,在前面的类 B 中,私有属性会被 Python 分别重命名为 _B__private _B__private_method 。这时候你可能会问这样重命名的目的是什么,答案就是继承——这种属性是无法通过继承来覆盖的(override)。比如:

class C(B):
    def __init__(self):
        super().__init__()
        self.__private = 1 # Does not override B.__private

    # Does not override B.__private_method()
    def __private_method(self):
        pass

这里,类 C 的私有名称 __private 和 __private_method 被 Python 重命名为 _C__private 和 _C__private_method ,这个跟父类 B 中的名称是完全不同的。

上面提到有两种不同的编码约定(单下划线和双下划线) 来命名私有属性,那么问题就来了:到底哪种方式好呢?大多数情况下,你应该让你的非公共名称以单下划线开头。但是,如果你清楚你的代码会涉及到子类,并且有些内部属性应该对子类隐藏起来,那么才考虑使用双下划线方案。

还有一点要注意的是,有时候你定义的一个变量和某个保留关键字冲突,这时候可以使用单下划线作为后缀来区分,例如:

lambda_ = 2.0 # Trailing _ to avoid clash with lambda keyword

这里我们并不使用单下划线前缀的原因是避免误解它的使用初衷(等同于说,使用单下划线前缀的目的是为了防止命名冲突而不是指明这个属性是私有的)。通过使用单下划线后缀可以把这两种情况区别开。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值