【问题标题】:single underscore vs double underscore encapsulation in pythonpython中的单下划线与双下划线封装
【发布时间】:2021-11-28 04:43:07
【问题描述】:

我看到在下划线的帮助下,可以在类中声明私有成员,但只有一个分数,它仍然可以在 main 中访问,但有两个则不是。如果两个使变量私有,那么为什么只有一个分数?单下划线变量的用途/目的是什么?

class Temp:
    def __init__(self):
    self.a = 123
    self._b = 123
    self.__c = 123

obj = Temp()
print(obj.a)
print(obj._b)
print(obj.__c)

【问题讨论】:

  • 是的@MisterMiyagi,我知道封装的概念,但我在python中不清楚
  • 嗯,大概a 是公开的,_a 是受保护的__a 是私有的。由于 Python 类是……与 C++/C#/……类不同的东西,但它并没有被强制执行。
  • @MisterMiyagi protected 在 Python 中并不是真正的东西。
  • @Matthias 其余的都不是。不过,这似乎是一个足够接近解释的类比。

标签: python class encapsulation


【解决方案1】:

这就是为什么这是“标准”,与其他语言略有不同。

  1. 没有下划线表示它是该类的用户可以触摸/修改/使用的公共事物
  2. 一个下划线更多的是一个实现细节,通常(注意这个词通常)应该只在子类中引用/使用,或者如果您知道自己在做什么。 python 的美妙之处在于我们都是成年人,如果有人想要访问一些真正自定义的东西,那么他们应该能够。
  3. 两个下划线是名称错位以包含类名,如_Temp__c 在幕后,以防止您的变量与子类发生冲突。但是,我会避免默认为两个,因为这不是一个好习惯,而且通常是不必要的。您可以阅读有关它的论点和其他帖子,例如this

注意:有或没有下划线的变量/方法没有区别。这只是一个约定,让社区没有强制执行而是接受为私有的类。
注意 #2:Matthias 描述了一个针对非类方法的异常

【讨论】:

  • 双前导下划线不用于使某些东西(超级)私有。这是为了防止子类化时的名称冲突。
  • 没错,我认为将其理解为“超级”私有的东西会更容易理解,而不是过于深入地进行名称冲突(正如我暗示的那样)。我将删除那部分。
  • “没有区别”不太对。不应该使用通配符导入,但它仍然完成了,from foo import * 不会导入名称以下划线开头的对象。当然这只适用于顶层对象,不适用于类的属性和方法。
  • 更具体地说,仅当名称以两个下划线开头并以零个或一个下划线结尾时才会发生名称修改。
  • @Matthias 我什至不知道这条规则。奇怪的是,我从来没有这样做过或遇到过这种情况,主要是因为我没有通配符。
【解决方案2】:

在 Python 中,没有存在“私有”实例变量,这些变量只能在对象内部访问。
然而,大多数 Python 代码和编码器都遵循一个约定,即一个带有下划线前缀的名称,例如 For e.g. _xyz 应被视为 API 或任何 Python 代码的非公共部分,无论是函数、方法还是数据成员

【讨论】:

  • 你能给我举个例子吗?这可以帮助澄清
  • @Ammar 看官方Style Guide for Python Code。引用 1:“仅对非公共方法和实例变量使用一个前导下划线。”。引用 2:“为避免名称与子类发生冲突,请使用两个前导下划线来调用 Python 的名称修饰规则。”
猜你喜欢
  • 1970-01-01
  • 2012-11-09
  • 2013-02-03
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
相关资源
最近更新 更多