在Python中,对象名称前的单前导下划线和双前导下划线代表什么?


当前回答

了解_和_的事实非常容易;其他答案很好地表达了这一点。这种用法很难确定。

我是这样看的:

_

应用于指示函数不供公共使用,例如API。这和导入限制使其行为与c#中的内部行为非常相似。

__

应用于避免继承层次结构中的名称冲突,并避免后期绑定。很像c#中的private。

==>

如果你想表明某些东西不是供公众使用的,但它应该像受保护的用途一样。如果你想表明某些东西不是公共使用的,但它应该像私人使用一样。

这也是我非常喜欢的一句话:

问题是,一个类的作者可能会合理地认为“属性/方法名称应该是私有的,只能从内部访问这个类定义”,并使用__private约定,该类的用户可以创建合法需要的子类访问该名称。所以要么必须修改超类(这可能很困难或不可能),或者子类代码必须使用手动损坏的名称(这充其量是丑陋和脆弱的)。

但在我看来,如果没有IDE在重写方法时发出警告,那么如果意外地从基类重写了方法,查找错误可能需要一段时间。

其他回答

_foo:只是惯例。程序员指示变量是私有的(无论在Python中意味着什么)。__foo:这有真正的意义。解释器将此名称替换为_classname__foo,以确保该名称不会与其他类中的类似名称重叠。__foo__:只是惯例。Python系统使用不会与用户名冲突的名称的方法。

在Python世界中,没有其他形式的下划线有意义。此外,在这些约定中,类、变量、全局等之间没有区别。

开头有一个下划线:

Python没有真正的私有方法。相反,方法或属性名称开头的一个下划线表示您不应该访问此方法,因为它不是API的一部分。

class BaseForm(StrAndUnicode):
    
    def _get_errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors

    errors = property(_get_errors)

(此代码片段取自django源代码:django/forms/forms.py)。在这段代码中,error是一个公共属性,但此属性调用的方法_get_errors是“私有”的,因此您不应该访问它。

开头有两个下划线:

这会引起很多混乱。它不应用于创建私有方法。应该使用它来避免方法被子类重写或意外访问。让我们看一个例子:

class A(object):
    def __test(self):
        print "I'm a test method in class A"

    def test(self):
        self.__test()
 
a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!

输出:

$ python test.py
I'm test method in class A
I'm test method in class A

现在创建一个子类B并为__test方法进行定制

class B(A):
    def __test(self):
        print "I'm test method in class B"

b = B()
b.test()

输出将是。。。。

$ python test.py
I'm test method in class A

正如我们所看到的,B.test()并没有像我们预期的那样调用B.__test()方法。但事实上,这是__的正确行为。名为__test()的两个方法会自动重命名(损坏)为_A__test()和_B__test(。当你创建一个以__开头的方法时,这意味着你不希望任何人能够覆盖它,你只想从它自己的类内部访问它。

开头和结尾有两个下划线:

当我们看到像__this___这样的方法时,不要调用它。这是python要调用的方法,而不是您。让我们来看看:

>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11

>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60

总是有一个运算符或本机函数调用这些神奇的方法。有时它只是在特定情况下python调用的钩子。例如,在调用__new__()构建实例后创建对象时调用__init__()。。。

让我们举个例子。。。

class FalseCalculator(object):

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

    def __add__(self, number):
        return self.number - number

    def __sub__(self, number):
        return self.number + number

number = FalseCalculator(20)
print number + 10      # 10
print number - 20      # 40

有关详细信息,请参阅[PEP-8指南][1]。有关更多神奇的方法,请参阅[本PDF][2]。[1]: https://www.python.org/dev/peps/pep-0008/#method-名称和实例变量[2] http://github.com/RafeKettler/magicmethods/blob/master/magicmethods.pdf

为了用简单的语言来描述它,让我们将python变量的可访问性约定与Java中的访问修饰符进行比较:

(Python)                                     =   (Java)
_single_underscore_variable                  =   Protected (Accessible to class and its subclasses)
__double_underscore_variable                 =   Private (Accessible to class itself only)
no_underscore_variable                       =   Public (Accessible anywhere)

参考:https://www.tutorialsteacher.com/python/public-private-protected-modifiers

有时,您会看到一个带有前导下划线的元组,如

def foo(bar):
    return _('my_' + bar)

在本例中,发生的情况是,_()是本地化函数的别名,该函数根据语言环境对文本进行操作以将其转换为适当的语言等。例如,Sphinx这样做,您可以在导入中找到

from sphinx.locale import l_, _

在sphinx.locale中,_()被指定为某个本地化函数的别名。

很好的答案,而且都是正确的。我提供了简单的例子以及简单的定义/含义。

含义:

某些变量--► 这是公开的,任何人都可以看到。

_某些变量--► 这是公开的,任何人都可以看到,但这是一个惯例,表明私人。。。警告Python不执行强制。

__某些变量--► Python将变量名替换为_classname__some_varable(AKA name mangling),并降低/隐藏其可见性,更像是私有变量。

老实说,根据Python文档

无法访问的“Private”实例变量Python中不存在对象“

示例:

class A():
    here="abc"
    _here="_abc"
    __here="__abc"


aObject=A()
print(aObject.here) 
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable 
#print(aObject.__here)