Python中的下划线

总览

分类

  • Single Leading Underscore: _var
  • Single Trailing Underscore: var_
  • Double Leading Underscore: __var
  • Double Leading and Trailing Underscore: __var__
  • Single Underscore: _

Single Leading Underscore

概述

  • 下划线前缀是向另外一个程序员的提示,即以单个下划线开头的变量或方法供内部使用。该约定在PEP 8中定义。
  • 这不是Python强制执行的。Python在“私有”和“公共”变量之间没有像Java那样强烈的区别。

示例

class Test:
    def __init__(self):
        self.foo = 11
        self._bar = 23
>>> t = Test()
>>> t.foo
11
>>> t._bar
23
  • Single Leading Underscore 并不能阻止咱们对其变量的访问,可是会影响从模块导入名称的方式,Python将不会导入带下划线的名称(除非模块定义了覆盖此行为的__all__列表)

Single Trailing Underscore

概述

  • 有时,关键字已经采用了最适合该变量的名称。所以,像Python这样的名称classdef不能将其用做变量名称。在这种状况下,您能够附加一个下划线以消除命名冲突
  • 总而言之,约定使用单个结尾的下划线(后缀)来避免与Python关键字命名冲突。PEP 8中对此约定进行了说明。

示例

>>> def make_object(name, class):
SyntaxError: "invalid syntax"

>>> def make_object(name, class_):
...     pass

Double Leading Underscore

概述

  • 双下划线前缀使Python解释器重写属性名称,以免子类中的命名冲突。
    • 原文参考:The naming patterns we covered so far received their meaning from agreed upon conventions only. With Python class attributes (variables and methods) that start with double underscores, things are a little different.
  • 这也称为名称修改-解释器以某种方式更改变量的名称,从而在之后扩展类时使建立冲突更加困难。
    • 原文参考:This is also called name mangling—the interpreter changes the name of the variable in a way that makes it harder to create collisions when the class is extended later.

示例

  • 让咱们使用内置dir()函数查看该对象的属性:python

    class Test:
        def __init__(self):
            self.foo = 11
            self._bar = 23
            self.__baz = 23
    >>> dir(t)
    ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bar', 'foo']
    • 仔细观察会发现缺乏属性__baz 这是Python解释程序应用的名称修饰。这样作是为了防止变量在子类中被覆盖。
    class ExtendedTest(Test):
        def __init__(self):
            super().__init__()
            self.foo = 'overridden'
            self._bar = 'overridden'
            self.__baz = 'overridden'
    >>> t2 = ExtendedTest()
    >>> t2.foo
    'overridden'
    >>> t2._bar
    'overridden'
    >>> t2.__baz
    AttributeError: 'ExtendedTest' object has no attribute '__baz'
    >>> dir(t2)
    ['_ExtendedTest__baz', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bar', 'foo']
    >>> t2._ExtendedTest__baz
    'overridden'
    >>> t2._Test__baz
    23
    • 双下划线名称改写对程序员是彻底透明的
    class ManglingTest:
        def __init__(self):
            self.__mangled = 'hello'
    
        def get_mangled(self):
            return self.__mangled
    >>> ManglingTest().get_mangled()
    'hello'
    >>> ManglingTest().__mangled
    AttributeError: "'ManglingTest' object has no attribute '__mangled'"
    • 名称修饰也适用于方法名称,名称修饰会影响在类上下文中以两个下划线字符(“ dunders”)开头的全部名称
    class MangledMethod:
        def __method(self):
            return 42
    
        def call_it(self):
            return self.__method()
    >>> MangledMethod().__method()
    AttributeError: "'MangledMethod' object has no attribute '__method'"
    >>> MangledMethod().call_it()
    42
    _MangledGlobal__mangled = 23
    
    class MangledGlobal:
        def test(self):
            return __mangled
    >>> MangledGlobal().test()
    23
    • 在此示例中,我声明了一个名为的全局变量_MangledGlobal__mangled。而后,我在名为的类的上下文中访问了变量MangledGlobal。因为名称修改,我可以_MangledGlobal__mangled像在类上的方法__mangled内部同样引用全局变量test()
    • Python解释器会自动将名称扩展为__mangled_MangledGlobal__mangled由于它以两个下划线字符开头。这代表名称修饰与类属性无关。它适用于任何以类上下文中使用的两个下划线字符开头的名称。

Double Leading and Trailing Underscore

概述

  • 若是名称以双下划线开头和结尾,则不该用名称修饰,可是,同时具备前导和尾随双下划线的名称保留给该语言特殊使用。该规则涵盖__init__了对象构造函数或__call__使对象可调用之类的内容。这些dunder方法一般被称为魔术方法
  • 最好不要在本身的程序中使用以双下划线(“ dunders”)开头和结尾的名称,以免与未来对Python语言的更改发生冲突。

示例

class PrefixPostfixTest:
    def __init__(self):
        self.__bam__ = 42
>>> PrefixPostfixTest().__bam__
42

Single Underscore

概述

  • 有时使用单个独立的下划线做为名称来表示变量是临时的或可有可无的。

示例

  • 您还能够在解包表达式中使用单个下划线做为“可有可无”变量来忽略特定值。一样,此含义仅是“按惯例”,而且在Python解释器中不会触发任何特殊行为。单个下划线只是一个有效的变量名,有时会用于此目的。
>>> for _ in range(3):
	print("Python")
	
Python
Python
Python
  • 在下面的代码示例中,我将一个car元组拆成单独的变量,可是我只对colorand的值感兴趣mileage。可是,为了使解包表达式成功,我须要将元组中包含的全部值分配给变量。那是“ _”用做占位符变量的地方
>>> car = ('red', 'auto', 12, 3812.4)
>>> color, _, _, mileage = car

>>> color
'red'
>>> mileage
3812.4
>>> _
12
  • 除了用做临时变量外,“ _”仍是大多数Python REPL中的特殊变量,它表明解释器评估的最后一个表达式的结果。若是您在解释器会话中工做,而且想访问之前的计算结果,这将很方便。或者,若是您正在动态构建对象,而且想与它们交互而不先给它们指定名称,则:
>>> 20 + 3
23
>>> _
23
>>> print(_)
23

>>> list()
[]
>>> _.append(1)
>>> _.append(2)
>>> _.append(3)
>>> _
[1, 2, 3]

参照

Pattern Example Meaning
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.
模式 含义
Single Leading Underscore _var 表示名称的命名约定仅供内部使用。一般不禁Python解释器强制执行(通配符导入除外),而且仅做为对程序员的提示。
Single Trailing Underscore var_ 按照惯例使用,以免与Python关键字命名冲突。
Double Leading Underscore __var 在类上下文中使用时触发名称修改。由Python解释器强制执行。
Double Leading and Trailing Underscore __var__ 表示由Python语言定义的特殊方法。避免为您本身的属性使用此命名方案。
Single Underscore _ 有时用做临时变量或可有可无变量的名称(“可有可无”)。另外:Python REPL中最后一个表达式的结果。

原文https://dbader.org/blog/meaning-of-underscores-in-python程序员

相关文章
相关标签/搜索