在对象名称之前,单个和双重下划线的含义是什么?

发布于 2025-01-23 15:23:43 字数 39 浏览 5 评论 0 原文

在Python中对象的名称代表之前,单个和双重领导下指标是什么?

What do single and double leading underscores before an object's name represent in Python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

爱殇璃 2025-01-30 15:23:43

一类中的单个下划线

,带有领先下划线的名称向其他程序员表示属性或方法旨在在该类中使用。但是,隐私不是任何方式执行的
在模块中使用领先的下划线进行功能表明不应从其他地方导入它。

来自 pep-8 样式指南:

_single_leading_underscore :弱“内部使用”指示器。例如,来自m import *的代码>不导入其名称以下划线开头的对象。

double double dusterscore(name mangling)

表单的任何标识符 __垃圾邮件(至少两个领先的下划线,最多有一个尾随下划线)被文本替换为 _CLASSNAME__SPAM ,其中 className 是当前的班级名称,带有领先的下划线剥离。此乱七八糟的是无需考虑标识符的句法位置,因此可以用来定义类别私有实例和类变量,方法,存储在Globals中的变量,甚至在实例中存储的变量。在其他课程的实例上,本班的私人。

并从同一页面发出警告:

名称杂交旨在为类提供一种简单的方法来定义“私有”实例变量和方法,而不必担心通过派生类定义的实例变量,或者通过类在类外部代码与实例变量弄乱。请注意,乱七八糟的规则主要是为了避免事故。 确定的灵魂仍然有可能访问或修改被认为是私人的变量。

示例

>>> 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

In a class, names with a leading underscore indicate to other programmers that the attribute or method is intended to be be used inside that class. However, privacy is not enforced in any way.
Using leading underscores for functions in a module indicates it should not be imported from somewhere else.

From the PEP-8 style guide:

_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!'}
你的往事 2025-01-30 15:23:43
  • _foo :只有一个约定。程序员表明该变量是私有的一种方法(无论在Python中意味着什么)。

  • __ foo :这具有真正的含义。解释器用 _CLASSNAME__FOO 替换此名称,以确保名称不会与其他类中的类似名称重叠。

  • __ foo __ :仅是约定。 Python系统使用不会与用户名相冲突的名称的一种方法。

在Python世界中,没有其他形式的下划线具有意义。同样,在这些惯例中,类,变量,全球等之间没有区别。

  • _foo: Only 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.

  • __foo__: Only a convention. A way for the Python system to use names that won't conflict with user names.

No other form of underscores have meaning in the Python world. Also, there's no difference between class, variable, global, etc in these conventions.

左秋 2025-01-30 15:23:43

到目前为止,出色的答案,但缺少一些花絮。单个领先的下划线不完全 一个惯例:如果您从foobar import *中使用,而模块 foobar 不定义 __所有__ 列表,从模块导入的名称 不包括带有领先下划线的名称。假设这是主要是的惯例,因为这种情况是一个非常晦涩的角落;-)。

领先的condent惯例不仅被广泛用于 private 名称,还用于C ++所谓的受保护的名称 - 例如,完全旨在完全旨在的方法的名称被子类(即使是已经被覆盖的子类)覆盖,因为在基类中,它们提高noctimplementedError ! - )通常是单个Leading-underScore名称,以指示代码<强>使用该类别(或子类)的实例,该类别并非直接调用所述方法。

例如,要使与FIFO不同的排队纪律制作线程安全队列,One inovers queue,subclasses queue.queue.queue和覆盖 _get> _get _put> _put 之类的方法; “客户端代码”从不调用这些(“钩”)方法,而是(“组织”)公共方法,例如 put get (这被称为< a href =“ http://en.wikipedia.org/wiki/wiki/template_method_pattern” rel =“ noreferrer”> template方法设计模式 - 请参阅eg 此处 基于关于我的主题的谈论的视频,并添加了有趣的演讲成绩单的概念)。

编辑:谈判描述中的视频链接现在被打破。您可以找到前两个视频在这里 .youtube.com/watch?v = tjxhtncdbu4“ rel =“ noreferrer”>在这里。

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.

逆流 2025-01-30 15:23:43

._变量是半剥夺的,仅对于惯例

.__变量通常被错误地考虑到超级私人,而其实际含义仅是namemangle到防止意外访问 [1]

.__ .__

您仍然可以访问。双重下调的只是namemangles或命名,将变量添加到 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 its 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

无法回应 2025-01-30 15:23:43

一开始的单个下划线:

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取的)。在此代码中,错误是公共属性,但是该属性调用的方法是_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

总有一个称为这些魔术方法的操作员或本机功能。有时候,这只是在特定情况下打电话的钩子。例如,当 __ 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指南 。有关更多魔术方法,请参见 this 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()

The output will be...

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

As we have seen, B.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 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.

内心荒芜 2025-01-30 15:23:43

根据 python中的

  • 含义代码> _VAR ):命名约定,指示该名称旨在内部使用。通常,Python的口译员(在通配符进口中除外)并不是对程序员的提示。
  • 单个尾随下划线( var _ :公约用来避免使用Python关键字命名冲突。
  • 双领先下划线( __ var :在课堂上下文中使用时触发名称杂物。由Python口译员执行。
  • 双领先和尾随下划线( __ var __ :指示由Python语言定义的特殊方法。避免使用您自己属性的这个命名方案。
  • 单个下划线( _ :有时用作临时或微不足道变量的名称(“不在乎”)。另外:python中最后一个表达式的结果 repl

According to 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.
呆° 2025-01-30 15:23:43

由于有很多人指的是雷蒙德的谈话写下他所说的话,这要容易一些:

双重下调的意图与隐私无关。目的是像这样使用它

  class Circle(对象):

    def __init __(自我,半径):
        self.radius =半径

    DEF区域(自我):
        p = self .__ ender()
        r = p / math.pi / 2.0
        返回Math.pi * r ** 2.0

    DEF周长(自我):
        返回2.0 * Math.pi * self.radius

    __ Perimeter =周长#本地参考


轮胎班级(圈):

    DEF周长(自我):
        返回圆圈。
 

实际上与隐私相反,这全都与自由有关。它使您的子类自由覆盖任何一种方法而不打破其他方法

假设您在 circle 中不保留外围的本地参考。现在,派生的类轮胎覆盖了周边的实现,而无需触摸 afear 。当您调用轮胎(5).AREA()时,理论上仍应使用 circle.perimeter 进行计算,但实际上它使用的是 tire.perimeter.perimeter.perimeter.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.

愁以何悠 2025-01-30 15:23:43

有时,您有一个带有领先强调的元组,如

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

在这种情况下,正在发生的事情是,_()是本地化函数的别名地方。例如,狮身人面像这样做,您将在Imports

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.

浅语花开 2025-01-30 15:23:43
  • _var :Python中带有领先单个下划线的变量是经典变量,旨在使用您的代码通知其他变量,以便将此变量保留为内部使用。它们在一个点上与经典变量有所不同:在执行定义的对象/模块的通配符导入的通配符导入时,它们没有被导入(定义

  • _ :单个下划线是领先的单个下划线变量的特殊情况。会议将其用作垃圾变量,以存储不打算以后访问的值。它也不是通配符进口的进口。例如:此循环打印“我必须在课堂上说话” 10次,而不需要访问 _ 变量。

     <代码> _在范围内(10):
        打印(“我不能在课堂上说话”)
     
  • var _ :单个尾随下划线变量。它们是公约使用的经典变量,以避免与Python关键字发生冲突。例如:

      class_ =“ myClassName”
     
  • __ var :双领先下划线变量(至少两个领先的下划线,最多有一个尾随下划线)。当用作类属性(变量和方法)时,这些变量将由名称进行杂交:班级之外,Python将将属性重命名为 _&lt; class_name&gt; __&gt; __&lt; attribute_name&gt; ; 。示例:

     类myclass:
        __an_attribute =“ attribute_value”
    
    my_class = myClass()
    打印(my_class._myclass__an_attribute)#“ attribute_value”
    print(my_class .__ an_attribute)#attributeError:'myclass'对象没有属性'__an_attribute'
     

    当类似于单个领先的下划线变量时,它们的表现是在类似的班级外部。

  • __ var __ :双向和尾随下划线变量(至少两个领先和尾随下划线)。也称为 dunders 。 Python使用此命名约定在内部定义变量。避免使用此约定来防止Python更新可能引起的名称冲突。 Dunder变量的行为就像单个领先的下划线变量:在类中使用时,它们不受名字的名称,而是在通配符导入中导入。

  • _var: variables with a leading single underscore in python are classic variables, intended to inform others using your code that this variable should be reserved for internal use. They differ on one point from classic variables: they are not imported when doing a wildcard import of an object/module where they are defined (exceptions when defining the __all__ variable). Eg:

    # foo.py
    
    var = "var"
    _var = "_var"
    
    # bar.py
    
    from foo import *
    
    print(dir())  # list of defined objects, contains 'var' but not '_var'
    print(var)    # var
    print(_var)   # NameError: name '_var' is not defined
    
  • _ : the single underscore is a special case of the leading single underscore variables. It is used by convention as a trash variable, to store a value that is not intended to be later accessed. It is also not imported by wildcard imports. Eg: this for loop prints "I must not talk in class" 10 times, and never needs to access the _ variable.

    for _ in range(10):
        print("I must not talk in class")
    
  • var_: single trailing underscore variables. They are classic variables used by convention to avoid conflicts with Python keyword. Eg:

    class_ = "MyClassName"
    
  • __var: double leading underscore variables (at least two leading underscores, at most one trailing underscore). When used as class attributes (variables and methods), these variables are subject to name mangling: outside of the class, python will rename the attribute to _<Class_name>__<attribute_name>. Example:

    class MyClass:
        __an_attribute = "attribute_value"
    
    my_class = MyClass()
    print(my_class._MyClass__an_attribute)  # "attribute_value"
    print(my_class.__an_attribute)  # AttributeError: 'MyClass' object has no attribute '__an_attribute'
    

    When used as variables outside a class, they behave like single leading underscore variables.

  • __var__: double leading and trailing underscore variables (at least two leading and trailing underscores). Also called dunders. This naming convention is used by python to define variables internally. Avoid using this convention to prevent name conflicts that could arise with python updates. Dunder variables behave like single leading underscore variables: they are not subject to name mangling when used inside classes, but are not imported in wildcard imports.

め可乐爱微笑 2025-01-30 15:23:43

如果一个人真的想制作一个只能读取的变量,那么恕我直言,最好的方法就是使用property(),而只通过getter将其传递给它。使用属性(),我们可以完全控制数据。

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.

愁杀 2025-01-30 15:23:43

很棒的答案,所有人都是正确的。我提供了简单的示例以及简单的定义/含义。

含义:

Some_variable--►是公众可以看到的。

_some_variable--►公众可以看到这一点,但这是指私人的惯例... 警告 python没有执行执行。

__SOME_VARAIBLE - ►Python用_ClassName__some_varable(又称名称mangling)替换了变量名称,并且它降低了/隐藏的视野,并且更像是私人变量。

老实说,在这里根据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)
蘸点软妹酱 2025-01-30 15:23:43

这是一个简单的说明性示例,介绍了双重下强度属性如何影响继承类。因此,使用以下设置:

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 Repp中创建一个子实例,您会看到以下

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

入怼 2025-01-30 15:23:43

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

双领先和尾随下划线用于内置方法,例如 __ INIT __ __ bool __ 等。double

引导下方均带有tailling对等方面的双领先底列,但是也是一个约定。类方法将为 mangled> mangled 解释者。对于变量或基本函数名称,没有差异。

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.

李不 2025-01-30 15:23:43

您的问题很好,不仅与方法有关。模块中的功能和对象通常也以一个下划线为前缀,并且可以由两个前缀。

但是__double_underscore名称并未在模块中使用名称。发生的事情是,如果您从模块中导入全部(从模块导入 *),则不会导入一个(或更多)下划线的名称,也不会在help(模块)中显示名称。

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).

强者自强 2025-01-30 15:23:43

除了从python中不存在外部对象外,无法访问的“私有”实例变量。但是,有大多数python代码之后的约定:以下划线(例如_spam)前缀的名称应视为API的非公共部分(无论是函数,方法还是数据成员) 。它应被视为实施细节,并有可能更改,恕不另行通知。

参考
https://dtps://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

溺渁∝ 2025-01-30 15:23:43

获得_和__的事实非常容易;其他答案很好地表达了他们。用法难以确定。

这就是我的看法:

_

应使用来指示函数不用于公众使用,例如API。这和导入限制使其行为与C#中的内部

__

应使用以避免在继承的遗迹中碰撞并避免隔离。很像C#中的私人。

==&gt;

如果要指出某物不是用于公共使用的东西,但应像受保护使用 _ 一样。
如果您想指出某物不是用于公共使用的东西,但应像 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.

白馒头 2025-01-30 15:23:43

对于方法,您可以使用双重下划线将私有“方法”隐藏为以下模式:

# Private methods of MyClass
def _MyClass__do_something(obj:'MyClass'):
    print('_MyClass__do_something() called. type(obj) = {}'.format(type(obj)))

class MyClass():
    def __init__(self):
        __do_something(self)

mc = MyClass()

输出:

_MyClass__do_something() called. type(obj) = <class '__main__.MyClass'>

当我尝试使用double double下划线用于类方法并获得 name eRror:name'name'时,我今天偶然发现了这一点。 _&lt; class&gt;&lt;未定义错误。

In the case of methods, you can use the double underscore to hide away private 'methods' with the following pattern:

# Private methods of MyClass
def _MyClass__do_something(obj:'MyClass'):
    print('_MyClass__do_something() called. type(obj) = {}'.format(type(obj)))

class MyClass():
    def __init__(self):
        __do_something(self)

mc = MyClass()

Output:

_MyClass__do_something() called. type(obj) = <class '__main__.MyClass'>

I stumbled across this today when I tried using double underscore for class methods and got the NameError: name '_<class><method>' is not defined error.

迷迭香的记忆 2025-01-30 15:23:43

要用简单的单词进行构架,让我们比较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-public-private-protected-modifiers

To frame it in simple words, let us compare python's variables' accessibility conventions to access modifiers in 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)

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

音盲 2025-01-30 15:23:43

_obj表示受保护(可以在定义类及其子类中访问)

- obj表示私有(它们无法从定义的班级外部直接访问它们。但是,Python并不像其他语言那样强制执行严格的私人访问;取而代之的是,它执行名称操作以使访问更加困难,但并非不可能。)

杂交是Python中的一个功能,它修改了类成员的名称,以使直接从班级外部直接访问。这是一种用于创建“伪私人”变量和方法的技术。这是通过将成员名称加上双重下划线(__)的前缀来完成

_obj means protected (can be accessed within the defining class and its subclasses)

--obj means private (They are not directly accessible from outside the class where they are defined. However, Python does not enforce strict private access like some other languages do; instead, it performs name mangling to make access more difficult but not impossible.)

Mangling is a feature in Python that modifies the name of a class member to make it harder to access directly from outside the class. It's a technique used to create "pseudo-private" variables and methods. This is done by prefixing the member name with a double underscore (__) but not ending with another double underscore

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文