Python中单/双下划线使用

本文详细解析了Python中不同类型的私有成员,包括特殊成员、真正私有成员、约定私有成员的区别及其应用场景,帮助读者深入理解Python的访问控制机制。

转载自:http://blog.youkuaiyun.com/my2010sam/article/details/10949717

在Python编程中经常会遇到函数(function),方法(method)及属性(attribute)以下划线'_'作为前缀,这里做个总结。
主要存在四种情形
      1. [python]  view plain  copy
        1. <span style="font-family:SimSun; font-size:18px">1. object # public  
        2.   
        3.   
        4. 2. __object__ # special, python system use, user should not define like it  
        5.   
        6.   
        7. 3. __object # private (name mangling during runtime)  
        8.   
        9.   
        10. 4. _object # obey python coding convention, consider it as private  
        11. </span>  

        通过上面的描述,1和2两种情形比较容易理解,不多做解释,最迷惑人的就是3和4情形。
      在解释3和4情形前,首先了解下python有关private的描述,python中不存在protected的概念,要么是public要么就是private,但是python中的private不像C++, Java那样,它并不是真正意义上的private,通过name mangling(名称改编,下面例子说明)机制就可以访问private了。

      针对 3:
       
      [python]  view plain  copy
      1. <span style="font-family:SimSun; font-size:18px">class Foo():  
      2.   
      3.     def __init__():  
      4.   
      5.         ...  
      6.   
      7.       
      8.   
      9.     def public_method():  
      10.   
      11.         print 'This is public method'  
      12.   
      13.   
      14.   
      15.     def __fullprivate_method():  
      16.   
      17.         print 'This is double underscore leading method'  
      18.   
      19.   
      20.   
      21.     def _halfprivate_method():  
      22.   
      23.         print 'This is one underscore leading method'  
      24. </span>  

      1. 然后我们实例化Foo的一个对象,看看结果就很清晰了:
      1. [python]  view plain  copy
        1. <span style="font-family:SimSun; font-size:18px">f = Foo()  
        2.   
        3.   
        4.   
        5. f.public_method() # OK  
        6.   
        7.   
        8.   
        9. f.__fullprivate_method() # Error occur  
        10.   
        11.   
        12.   
        13. f._halfprivate_method() # OK  
        14. </span>  

        1. 上文已经说明了,python中并没有真正意义的private,见以下方法便能够访问__fullprivate_method()
          1. [python]  view plain  copy
            1. <span style="font-family:SimSun; font-size:18px">f._Foo__fullprivate()_method() # OK</span>  
          2. [python]  view plain  copy
            1. <span style="font-size:18px">  
            2.   
            3. </span>  
            [python]  view plain  copy
            1. <ol><li><span style="font-size:18px"><span style="font-family:SimSun"><span style="color:#0000ff">print</span> dir<span style="color:#0000cc">(</span>f<span style="color:#0000cc">)</span>  
            2. </span></span></li></ol>  

            ['_Foo__fullprivate_method','_halfprivate_method','public_method',...]

          所谓的name mangling就是将__fullprivate_method替换成了_Foo__fullprivate_method,目的就是以防子类意外重写基类的方法或者属性。


          允许通过类内部方法访问其他私有方法,如下:



          针对4:
          从上面的例子可以看出,f._halfprivate_method()可以直接访问,确实是。不过根据python的约定,应该将其视作private,而不要在外部使用它们,(如果你非要使用也没辙),良好的编程习惯是不要在外部使用它咯。
          同时,根据Python docs的说明,_object和__object的作用域限制在本模块内,见以下示例:
              1. [python]  view plain  copy
                1. <span style="font-family:SimSun; font-size:18px">''''' 
                2.  
                3. A.py 
                4.  
                5. '''  
                6.   
                7. def _nok(): # __nok() same as _nok()  
                8.   
                9.    ...  
                10.   
                11. def ok():  
                12.   
                13.     ...  
                14. </span>  

              2. [python]  view plain  copy
                1. ''''' 
                2.  
                3. <span style="font-family:SimSun; font-size:18px">B.py 
                4.  
                5. '''  
                6.   
                7. from A import *  
                8.   
                9.   
                10. ok() # work well  
                11.   
                12.   
                13. _nok() # error occur  
                14.   
                15.   
                16. __nok() # error occur  
                17. </span>  


               
               
               
               
               
               
               
               
               
               
               
               
               
               
               
              通过上面的例子就能很好地把握有关下划线的细节了,平时还是需要多动手练练。

              ### Python下划线下划线的区别 #### 下划线 `_variable` 在 Python 编码约定中,以下划线开头的成员名(如 `_object`),通常表示该成员是受保护的或私有的。这种命名方式是一种惯例,并不强制执行访问控制;它更多是为了提醒开发者这些属性不应该直接访问。 ```python class Example: def __init__(self): self._private_var = "This is a protected variable" example_instance = Example() print(example_instance._private_var) # 虽然可以访问,但这不符合编码规范 ``` #### 下划线 `__variable` 当类中的属性名以前置下划线定义时(如 `__object`),Python 解释器会对这个名称进行重写处理,即所谓的“名称改写”(name mangling),目的是为了防止子类意外覆盖基类的方法或属性[^2]。 ```python class BaseClass: def __init__(self): self.__mangled_variable = "Mangled Variable" base_instance = BaseClass() # 尝试直接访问会引发 AttributeError 错误 try: print(base_instance.__mangled_variable) except AttributeError as e: print(f"Error: {e}") # 实际上可以通过特定的方式访问到被改写的变量 print(base_instance._BaseClass__mangled_variable) # 输出 Mangled Variable ``` #### 特殊方法 `__method__` 对于前后都带有下划线的形式(如 `__object__`),这类标识符被称为魔术方法或者是特殊方法。它们是由 Python 自身使用的,用来实现某些内置功能或是操作符重载等功能。例如: - `__init__`: 构造函数,在创建新实例时自动调用。 - `__str__`: 返回对象的字符串表示形式,用于打印输出。 ```python class MyClass: def __init__(self, value): self.value = value def __str__(self): return f"MyClass instance with value={self.value}" my_object = MyClass(42) print(my_object) # 使用 __str__() 方法来显示自定义消息 ```
              评论
              成就一亿技术人!
              拼手气红包6.0元
              还能输入1000个字符
               
              红包 添加红包
              表情包 插入表情
               条评论被折叠 查看
              添加红包

              请填写红包祝福语或标题

              红包个数最小为10个

              红包金额最低5元

              当前余额3.43前往充值 >
              需支付:10.00
              成就一亿技术人!
              领取后你会自动成为博主和红包主的粉丝 规则
              hope_wisdom
              发出的红包
              实付
              使用余额支付
              点击重新获取
              扫码支付
              钱包余额 0

              抵扣说明:

              1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
              2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

              余额充值