问题:对象名称前的单下划线和双下划线是什么意思?

有人可以解释一下在Python中对象名称前加下划线的确切含义,以及两者之间的区别吗?

此外,无论所讨论的对象是变量,函数,方法等,该含义是否都保持不变?

Can someone please explain the exact meaning of having leading underscores before an object’s name in Python, and the difference between both?

Also, does that meaning stay the same whether the object in question is a variable, a function, a method, etc.?


回答 0

单下划线

类中带有下划线的名称仅是为了向其他程序员表明该属性或方法旨在私有。但是,名称本身并没有做任何特别的事情。

引用PEP-8

_single_leading_underscore:“内部使用”指标较弱。例如from M import *,不导入名称以下划线开头的对象。

双下划线(名称改写)

Python文档

形式上的任何标识符__spam(至少两个前导下划线,至多一个尾随下划线)在文本上均替换为_classname__spam,其中classname是当前类名,其中已删除前导下划线。进行这种修饰时无需考虑标识符的语法位置,因此可用于定义类私有实例和类变量,方法,全局变量中存储的变量,甚至实例中存储的变量。在其他类的实例上对此类私有。

和来自同一页面的警告:

名称修饰旨在为类提供一种轻松的方法来定义“私有”实例变量和方法,而不必担心派生类定义的实例变量或类外部代码对实例变量的处理。请注意,修改规则主要是为了避免发生意外。坚定的灵魂仍然有可能访问或修改被视为私有的变量。

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

Single Underscore

Names, in a class, with a leading underscore are simply to indicate to other programmers that the attribute or method is intended to be private. However, nothing special is done with the name itself.

To quote PEP-8:

_single_leading_underscore: weak “internal use” indicator. E.g. from M import * does not import objects whose name starts with an underscore.

Double Underscore (Name Mangling)

From the Python docs:

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.

And a warning from the same page:

Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.

Example

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

回答 1

到目前为止,很好的答案,但缺少一些花絮。单个前导下划线并不仅仅是一个约定:如果使用from foobar import *,并且模块foobar未定义__all__列表,则从模块导入的名称将包括带有下划线的名称。可以说这主要是一个约定,因为这种情况是一个相当模糊的角落;-)。

领先的下划线惯例被广泛用于不只是私人的名字,而且对什么C ++称之为保护的-例如,都完全的方法名称由子类(甚至是那些覆盖被否决,因为在它们的基类raise NotImplementedError!-)通常是单引号下划线名称,用于指示使用该类(或子类)的实例进行编码时,这些方法并不旨在被直接调用。

例如,要创建一个与FIFO不同的排队规则的线程安全队列,可以导入Queue,将Queue.Queue子类化,并覆盖诸如_get_put;之类的方法。“客户端代码”从不调用那些(“挂钩”)方法,而是调用(和“组织”)公共方法,例如putget(称为模板方法设计模式),例如,有关基于视频的有趣演示,请参见此处。我关于这个话题的演讲,以及抄本的提要)。

编辑:演讲说明中的视频链接现在已断开。您可以在此处此处找到前两个视频。

Excellent answers so far but some tidbits are missing. A single leading underscore isn’t exactly just a convention: if you use from foobar import *, and module foobar does not define an __all__ list, the names imported from the module do not include those with a leading underscore. Let’s say it’s mostly a convention, since this case is a pretty obscure corner;-).

The leading-underscore convention is widely used not just for private names, but also for what C++ would call protected ones — for example, names of methods that are fully intended to be overridden by subclasses (even ones that have to be overridden since in the base class they raise NotImplementedError!-) are often single-leading-underscore names to indicate to code using instances of that class (or subclasses) that said methods are not meant to be called directly.

For example, to make a thread-safe queue with a different queueing discipline than FIFO, one imports Queue, subclasses Queue.Queue, and overrides such methods as _get and _put; “client code” never calls those (“hook”) methods, but rather the (“organizing”) public methods such as put and get (this is known as the Template Method design pattern — see e.g. here for an interesting presentation based on a video of a talk of mine on the subject, with the addition of synopses of the transcript).

Edit: The video links in the description of the talks are now broken. You can find the first two videos here and here.


回答 2

__foo__:这只是一个约定,这是Python系统使用不会与用户名冲突的名称的一种方式。

_foo:这只是一个约定,是程序员用来表明变量是私有的(无论在Python中是什么意思)的一种方式。

__foo:这具有实际含义:解释器将其替换为,_classname__foo以确保该名称不会与另一个类中的相似名称重叠。

在Python世界中,没有其他形式的下划线具有意义。

在这些约定中,类,变量,全局等之间没有区别。

__foo__: this is just a convention, a way for the Python system to use names that won’t conflict with user names.

_foo: this is just a convention, a way for the programmer to indicate that the variable is private (whatever that means in Python).

__foo: this has real meaning: the interpreter replaces this name with _classname__foo as a way to ensure that the name will not overlap with a similar name in another class.

No other form of underscores have meaning in the Python world.

There’s no difference between class, variable, global, etc in these conventions.


回答 3

._variable 是半私有的,仅用于约定

.__variable通常被错误地认为是超私有的,而其实际含义只是为了防止意外访问而使用 namemangle [1]

.__variable__ 通常为内置方法或变量保留

您仍然可以.__mangled根据需要访问变量。双下划线只是将变量命名或重命名为类似instance._className__mangled

例:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b是可访问的,因为它仅被约定隐藏

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

找不到t .__ a,因为由于名称修改而不再存在

>>> t._Test__a
'a'

通过访问instance._className__variable而不只是双下划线名称,您可以访问隐藏值

._variable is semiprivate and meant just for convention

.__variable is often incorrectly considered superprivate, while it’s actual meaning is just to namemangle to prevent accidental access[1]

.__variable__ is typically reserved for builtin methods or variables

You can still access .__mangled variables if you desperately want to. The double underscores just namemangles, or renames, the variable to something like instance._className__mangled

Example:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b is accessible because it is only hidden by convention

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

t.__a isn’t found because it no longer exists due to namemangling

>>> t._Test__a
'a'

By accessing instance._className__variable instead of just the double underscore name, you can access the hidden value


回答 4

开头下划线:

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)。在这段代码中,它errors是一个公共属性,但是此属性调用的方法_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

如我们所见,A.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的一个钩子调用。例如__init__()在创建对象之后创建对象时__new__()调用,以构建实例…

让我们举个例子…

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指南。有关更多魔术方法,请参见此PDF

Single underscore at the beginning:

Python doesn’t have real private methods. Instead, one underscore at the start of a method or attribute name means you shouldn’t access this method, because it’s not part of the 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)

(This code snippet was taken from django source code: django/forms/forms.py). In this code, errors is a public property, but the method this property calls, _get_errors, is “private”, so you shouldn’t access it.

Two underscores at the beginning:

This causes a lot of confusion. It should not be used to create a private method. It should be used to avoid your method being overridden by a subclass or accessed accidentally. Let’s see an example:

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!

Output:

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

Now create a subclass B and do customization for __test method

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

b = B()
b.test()

Output will be….

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

As we have seen, A.test() didn’t call B.__test() methods, as we might expect. But in fact, this is the correct behavior for __. The two methods called __test() are automatically renamed (mangled) to _A__test() and _B__test(), so they do not accidentally override. When you create a method starting with __ it means that you don’t want to anyone to be able to override it, and you only intend to access it from inside its own class.

Two underscores at the beginning and at the end:

When we see a method like __this__, don’t call it. This is a method which python is meant to call, not you. Let’s take a look:

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

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

There is always an operator or native function which calls these magic methods. Sometimes it’s just a hook python calls in specific situations. For example __init__() is called when the object is created after __new__() is called to build the instance…

Let’s take an example…

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

For more details, see the PEP-8 guide. For more magic methods, see this PDF.


回答 5

有时您看起来像是一个带下划线的元组,如下所示

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

在这种情况下,正在发生的情况是_()是本地化功能的别名,该功能基于文本在文本上进行操作以将其放入适当的语言等。例如,Sphinx执行此操作,您将在导入文件中找到

from sphinx.locale import l_, _

在sphinx.locale中,_()被分配为某些本地化功能的别名。

Sometimes you have what appears to be a tuple with a leading underscore as in

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

In this case, what’s going on is that _() is an alias for a localization function that operates on text to put it into the proper language, etc. based on the locale. For example, Sphinx does this, and you’ll find among the imports

from sphinx.locale import l_, _

and in sphinx.locale, _() is assigned as an alias of some localization function.


回答 6

既然有这么多人在谈论雷蒙德的演讲,我将写下他的话简化一下:

双下划线的目的不是关于隐私。目的是像这样完全使用它

class Circle(object):

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

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

实际上,这是隐私的对立面,它与自由有关。它使您的子类可以随意覆盖任何一种方法而不会破坏其他方法

假设您没有保留perimeterin 的本地引用Circle。现在,派生类将Tire覆盖实现perimeter,而无需触摸areaTire(5).area()从理论上讲,当您调用时,它仍Circle.perimeter应用于计算,但实际上,它正在使用Tire.perimeter,这不是预期的行为。这就是为什么我们在Circle中需要本地引用。

但是为什么要__perimeter代替_perimeter呢?因为_perimeter仍然给派生类重写的机会:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

双下划线具有名称修饰,因此父类中的本地引用在派生类中被覆盖的可能性很小。因此“ 使子类可以自由地覆盖任何一种方法而不会破坏其他方法 ”。

如果您的类不会被继承,或者方法重写不会破坏任何内容,那么您根本不需要__double_leading_underscore

Since so many people are referring to Raymond’s talk, I’ll just make it a little easier by writing down what he said:

The intention of the double underscores was not about privacy. The intention was to use it exactly like this

class Circle(object):

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

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

It’s actually the opposite of privacy, it’s all about freedom. It makes your subclasses free to override any one method without breaking the others.

Say you don’t keep a local reference of perimeter in Circle. Now, a derived class Tire overrides the implementation of perimeter, without touching area. When you call Tire(5).area(), in theory it should still be using Circle.perimeter for computation, but in reality it’s using Tire.perimeter, which is not the intended behavior. That’s why we need a local reference in Circle.

But why __perimeter instead of _perimeter? Because _perimeter still gives derived class the chance to override:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

Double underscores has name mangling, so there’s a very little chance that the local reference in parent class get override in derived class. thus “makes your subclasses free to override any one method without breaking the others“.

If your class won’t be inherited, or method overriding does not break anything, then you simply don’t need __double_leading_underscore.


回答 7

如果您真的想将变量设为只读,恕我直言,最好的方法是使用仅传递有getter的property()。使用property(),我们可以完全控制数据。

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

我知道OP提出了一个稍有不同的问题,但是由于我发现了另一个问题,询问“如何设置私有变量”与此标记为重复,因此我想在此处添加此附加信息。

If one really wants to make a variable read-only, IMHO the best way would be to use property() with only getter passed to it. With property() we can have complete control over the data.

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

I understand that OP asked a little different question but since I found another question asking for ‘how to set private variables’ marked duplicate with this one, I thought of adding this additional info here.


回答 8

进入https://dbader.org/blog/含义-underscores-in-python

  • 单个前导下划线(_var):表示名称的命名约定仅供内部使用。通常不由Python解释器强制执行(通配符导入除外),并且仅作为对程序员的提示。
  • 单个尾随下划线(var_):按惯例用于避免与Python关键字命名冲突。
  • 双引号下划线(__var):在类上下文中使用时触发名称修饰。由Python解释器实施。
  • 前后双下划线(__var__):表示Python语言定义的特殊方法。避免为您自己的属性使用此命名方案。
  • 单个下划线(_):有时用作临时或无关紧要的变量的名称(“无关紧要”)。另外:Python REPL中最后一个表达式的结果。

Accroding to https://dbader.org/blog/meaning-of-underscores-in-python

  • Single Leading Underscore(_var): Naming convention indicating a name is meant for internal use. Generally not enforced by the Python interpreter (except in wildcard imports) and meant as a hint to the programmer only.
  • Single Trailing Underscore(var_): Used by convention to avoid naming conflicts with Python keywords.
  • Double Leading Underscore(__var): Triggers name mangling when used in a class context. Enforced by the Python interpreter.
  • Double Leading and Trailing Underscore(__var__): Indicates special methods defined by the Python language. Avoid this naming scheme for your own attributes.
  • Single Underscore(_): Sometimes used as a name for temporary or insignificant variables (“don’t care”). Also: The result of the last expression in a Python REPL.

回答 9

单个下划线是惯例。名称是否以单个下划线开头,与解释器的观点没有区别。

双开头和结尾的下划线用于内置的方法,如__init____bool__

双下划线开头W / O尾随同行是惯例也是如此,但是,该类方法将被错位的解释。对于变量或基本函数名称,没有区别。

Single leading underscores is a convention. there is no difference from the interpreter’s point of view if whether names starts with a single underscore or not.

Double leading and trailing underscores are used for built-in methods, such as __init__, __bool__, etc.

Double leading underscores w/o trailing counterparts are a convention too, however, the class methods will be mangled by the interpreter. For variables or basic function names no difference exists.


回答 10

好的答案都正确。我提供了简单的示例以及简单的定义/含义。

含义:

some_variable–►任何人都可以看到这是公开的。

_some_variable–►任何人都可以看到这是公开的,但这是表示私有的惯例… 警告 Python不会执行任何强制执行。

__some_varaible–►Python将变量名替换为_classname__some_varaible(又名名称改写),它降低/隐藏了它的可见性,更像是私有变量。

坦白地说,根据Python文档

“只能从对象内部访问的“私有”实例变量在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)

Great answers and all are correct.I have provided simple example along with simple definition/meaning.

Meaning:

some_variable –► it’s public anyone can see this.

_some_variable –► it’s public anyone can see this but it’s a convention to indicate private…warning no enforcement is done by Python.

__some_varaible –► Python replaces the variable name with _classname__some_varaible (AKA name mangling) and it reduces/hides it’s visibility and be more like private variable.

Just to be honest here According to Python documentation

““Private” instance variables that cannot be accessed except from inside an object don’t exist in Python”

The example:

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)

回答 11

您的问题很好,不仅是方法。模块中的函数和对象通常也以一个下划线为前缀,并且可以以两个为前缀。

但是,例如,__double_underscore名称在模块中没有名称混杂。发生的情况是,如果您从模块(从module import *)全部导入,则不会导入以一个(或多个)下划线开头的名称,也不会在help(module)中显示名称。

Your question is good, it is not only about methods. Functions and objects in modules are commonly prefixed with one underscore as well, and can be prefixed by two.

But __double_underscore names are not name-mangled in modules, for example. What happens is that names beginning with one (or more) underscores are not imported if you import all from a module (from module import *), nor are the names shown in help(module).


回答 12

这是一个关于双下划线属性如何影响继承的类的简单说明性示例。因此,使用以下设置:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

如果您随后在python REPL中创建一个子实例,则会看到以下内容

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

这对于某些人可能是显而易见的,但是在更复杂的环境中使我措手不及

Here is a simple illustrative example on how double underscore properties can affect an inherited class. So with the following setup:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

if you then create a child instance in the python REPL, you will see the below

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

This may be obvious to some, but it caught me off guard in a much more complex environment


回答 13

Python中不存在只能从对象内部访问的“私有”实例变量。但是,大多数Python代码遵循一个约定:以下划线开头的名称(例如_spam)应被视为API的非公开部分(无论是函数,方法还是数据成员) 。它应被视为实现细节,如有更改,恕不另行通知。

参考 https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

reference https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references


回答 14

得到_和__的事实非常容易。其他答案很好地表达了他们。使用情况很难确定。

这是我的看法:

_

应该用于表示某个功能不公开使用,例如API。这和导入限制使它的行为很像internal在c#中。

__

应该用来避免继承层次结构中的名称冲突以及避免后期绑定。就像C#中的private。

==>

如果您想指出某事不是公共用途,而是应该像protecteduse 一样_。如果您想指出某事不是公共用途,而是应该像privateuse 一样__

这也是我非常喜欢的报价:

问题在于,类的作者可能会合理地认为“此属性/方法名称应为私有的,只能从该类定义中访问”,并使用__private约定。但是稍后,该类的用户可能会创建合法需要访问该名称的子类。因此,要么必须修改超类(可能很难或不可能),要么子类代码必须使用手动修改的名称(充其量是丑陋和脆弱的)。

但是我的问题是,如果没有IDE在您重写方法时警告您,如果您意外地从基类中重写了一个方法,则发现错误可能会花费您一段时间。

Getting the facts of _ and __ is pretty easy; the other answers express them pretty well. The usage is much harder to determine.

This is how I see it:

_

Should be used to indicate that a function is not for public use as for example an API. This and the import restriction make it behave much like internal in c#.

__

Should be used to avoid name collision in the inheritace hirarchy and to avoid latebinding. Much like private in c#.

==>

If you want to indicate that something is not for public use, but it should act like protected use _. If you want to indicate that something is not for public use, but it should act like private use __.

This is also a quote that I like very much:

The problem is that the author of a class may legitimately think “this attribute/method name should be private, only accessible from within this class definition” and use the __private convention. But later on, a user of that class may make a subclass that legitimately needs access to that name. So either the superclass has to be modified (which may be difficult or impossible), or the subclass code has to use manually mangled names (which is ugly and fragile at best).

But the problem with that is in my opinion that if there’s no IDE that warns you when you override methods, finding the error might take you a while if you have accidentially overriden a method from a base-class.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。