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程序員

相關文章
相關標籤/搜索