南风北巷

有幸偶遇诸多奇景

导航

统计

python中单下划线与双下划线命名变量的作用与区别

在python中有一些与下划线相关的约定,这是一个有趣的主题,值得分析分析。对于变量前面有一个下划线,大家都知道这意味着这个变量是类内私有变量,但是奇怪的是这样的类内变量是可以被外部引用的。

class Connector:
    def __init__(self, source) -> None:
        self.source = source
        self._timeout = 60

def main():
    connector = Connector('postgresql://localhost')
    print(connector._timeout) 
    print(connector.__dict__)

if __name__ == '__main__':
    main()

输出

60
{'source': 'postgresql://localhost', '_timeout': 60}

这样就让大家觉得很奇怪,明明是私有的,怎么外部变量也可以访问?这真是个天大的误会,其实这只是个约定的规则,python用这种方式来界定接口与私有属性,这种写法告诉程序员,我们可以安全地重构timeout这个变量而不会影响接口,因为外部不会调用类内私有属性和方法,重构代码时保持接口不变,就不会担心出现连锁反应。实际上,类应该只暴露与外部调用者对象相关的属性和方法,也就是接口指定的属性和方法,对于接口未指定的属性和方法,其名称都应以单下划线的方式开头。
对于以下划线开头的属性和方法不应该在外部调用它,但是在单元测试时,通过外部访问内部属性的方式可以简化测试,这种实用主义的方法可能付出维护性方面的代价。

对于变量有两个下划线的情况,那更是误会发生的地方。

class Connector:
    def __init__(self, source) -> None:
        self.source = source
        self.__timeout = 60

def main():
    connector = Connector('postgresql://localhost')
    print(connector.__timeout) 

if __name__ == '__main__':
    main()

输出

AttributeError: 'Connector' object has no attribute '__timeout'

许多程序员坚定不移,认为这就是私有变量的实现方式,实际不然,返回的错误是没有找到__timeout这个属性,这也就意味着它不是无法访问,而是出现了其它问题。
实际上,对于名称为双下划线开头的变量,python给它重命名为_<类名>__<属性名>,__timeout被重命名成了_Connector__timeout,因此可以这样访问它:

class Connector:
    def __init__(self, source) -> None:
        self.source = source
        self.__timeout = 60

def main():
    connector = Connector('postgresql://localhost')
    print(connector._Connector__timeout) 

if __name__ == '__main__':
    main()

输出

60

实际上,python并不是为了隐藏,而是为了覆盖将被扩展多次的方法,以消除方法名发生冲突的风险,这种理由听起来比较牵强,也不足以证明这种方式是值得的。
使用双下划线并不符合python语言习惯,要将属性定义为私有,请用单下划线,并遵守python约定。

posted on   _南风北巷  阅读(380)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示