Python – _ (底線) 與 _ _(雙底線)

第一次看到 Python 的 Code 時候發現寫法使用很多 _ (底線) 與 _ _(雙底線),原來是有其建議規定的. 參考文章 – https://medium.com/bits-to-blocks/python%E4%B8%AD%E7%9A%84underscore-%E8%88%87-9b40caf32483

  • _single_leading_underscore

    1. Class 屬性 (Attribute) 使用 _attribute 這種命名規則時是不希望它被直接被存取.
      [root@localhost ~]# vi underscore1.py
      class data:
          def __init__(self, data1 , data2):
              self.data1 = data1
              self._data2 = data2
      
      a = data(1,2)
      print(a.data1)
      print(a._data2)
      print(a.data2)
      

      執行結果,雖然 data2 無法存取,但是 _data2 還是可以存取.

      [root@localhost ~]# python3 underscore1.py
      1
      2
      Traceback (most recent call last):
        File "underscore1.py", line 9, in <module>
          print(a.data2)
      AttributeError: 'data' object has no attribute 'data2'
      
    2. 使用在 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_

    我們的命名可以使用 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

    1. 使用在 Class 屬性 (Attribute) 使用 __attribute 這種命名規則時是不希望它被直接被存取(同 _attribute?).
      [root@localhost ~]# cat 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'
      
    2. 避免 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_sum(5))
      print(cdata.sum)
      

      執行結果, 可以看到輸出 是 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_sum(5))
      print(cdata.sum)
      

      執行結果, 可以看到輸出 是 10 (使用到 C1 的 data 值)+5=15

      [root@localhost ~]# python3 underscore3.py
      15
      2
      
  • __double_leading_and_trailing_underscore__

    這是些 python 自身定義好使用雙底線的關鍵字.常見的如 __init__ , __new__ , __file__ , __eq__ 等…

沒有解決問題,試試搜尋本站其他內容

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料