第一次看到 Python 的 Code 時候發現寫法使用很多 _ (底線) 與 _ _(雙底線),原來是有其建議規定的. 參考文章 – https://medium.com/bits-to-blocks/python%E4%B8%AD%E7%9A%84underscore-%E8%88%87-9b40caf32483
關於 _single_leading_underscore , single_trailing_underscore_ , __double_leading_underscore 與 __double_leading_and_trailing_underscore__ 的定義在 – https://peps.python.org/pep-0008/
-
_single_leading_underscore
weak “internal use” indicator. E.g. from M import * does not import objects whose names start with an underscore.
使用在 Class 時 from Module_Name import * 將不導入名稱有_ (底線)的函數.
[root@localhost ~]# vi underscore_fun.py def add_data(data1 , data2): return data1+data2 def _sub_data(data1 , data2): return data1-data2
[root@localhost ~]# vi underscore4.py from underscore_fun import * print(add_data(2,3)) print(_sub_data(2,3))
執行結果, 可以發現 _sub_data 並沒有被匯入.
[root@localhost ~]# python3 underscore4.py 5 Traceback (most recent call last): File "underscore4.py", line 4, in <module> print(_sub_data(2,3)) NameError: name '_sub_data' is not defined
如要強制匯入需指定.
[root@localhost ~]# vi underscore5.py from underscore_fun import add_data , _sub_data print(add_data(2,3)) print(_sub_data(2,3))
執行結果
[root@localhost ~]# python3 underscore5.py 5 -1
或是在 Module 裡面加入 __all__ 即可成功import
[root@localhost ~]# vi underscore_fun.py def add_data(data1 , data2): return data1+data2 def _sub_data(data1 , data2): return data1-data2 __all__ = ['add_data', '_sub_data']
[root@localhost ~]# vi underscore4.py from underscore_fun import * print(add_data(2,3)) print(_sub_data(2,3))
執行結果
[root@localhost ~]# python3 underscore4.py 5 -1
-
single_trailing_underscore_
used by convention to avoid conflicts with Python keyword, e.g. tkinter.Toplevel(master, class_=’ClassName’)
我們的命名可以使用 name_ 來避免跟 Python 的關鍵字衝突.
以下是 python keyword 列表.
[root@localhost ~]# python3 Python 3.6.8 (default, Mar 25 2022, 11:15:52) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import keyword >>> print(keyword.kwlist) ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
-
__double_leading_underscore
when naming a class attribute, invokes name mangling.
- 使用在 Class 屬性 (Attribute) 使用 __attribute 這種命名規則時是不希望它被直接被存取.
[root@localhost ~]# vi underscore2.py class data: def __init__(self, data1 , data2 ): self.data1 = data1 self.__data2 = data2 a = data(1,2) print(a.data1) print(a.__data2)
執行結果
[root@localhost ~]# python3 underscore2.py 1 Traceback (most recent call last): File "underscore2.py", line 8, in <module> print(a.__data2) AttributeError: 'data' object has no attribute '__data2'
__attribute 還是可以透過 _類別名稱+屬性名稱 的方式來存取.不建議這麼做,最好不要讓外界知道其存在.
print(a._data__data2)
正規要存取 __attribute 需透過 @Property 包含 setter , getter 與 deleter 等方法 (Method) 來存取 – https://benjr.tw/104268
- 避免 Class 子類別繼承時所發生的名稱衝突(name clashes).
父子類別皆使用到 data 這個名稱的屬性.[root@localhost ~]# vi underscore3.py class C1: data = 10 def get_data(self): return self.data class C2(C1): def add_data(self,num): self.data = 2 return self.get_data() + num cdata = C2() print(cdata.add_data(5)) print(cdata.data)
執行結果, 可以看到輸出 是 2 (使用到 C2 的 data 值)+5=7
[root@localhost ~]# python3 underscore3.py 7 2
為避免 Class 子類別繼承時所發生的名稱衝突(name clashes),父類別屬性使用 __attribute .下面範例 C1 類別 data 屬性使用 __data 來取代.
[root@localhost ~]# vi underscore3.py class C1: __data = 10 def get_data(self): return self.__data class C2(C1): def add_data(self,num): self.data = 2 return self.get_data() + num cdata = C2() print(cdata.add_data(5)) print(cdata.data)
執行結果, 可以看到輸出 是 10 (使用到 C1 的 data 值)+5=15
[root@localhost ~]# python3 underscore3.py 15 2
- 使用在 Class 屬性 (Attribute) 使用 __attribute 這種命名規則時是不希望它被直接被存取.
-
__double_leading_and_trailing_underscore__
“magic” objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.
這是些 python 自身定義好使用雙底線的關鍵字.常見的如 __init__ , __new__ , __file__ , __eq__ 等…