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约定。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构