• Python类私有方法的陷阱


    引言

    Python不像C++、Java、C#等有明白的公共、私有或受保护的keyword来定义成员函数或属性,它使用约定的单下划线“_"和"__"双下划线作为函数或属性的前缀来标识。使用单下划线还是双下划线,是有非常大的差别的。

    1. 单下划线的函数或属性。在类定义中能够调用和訪问。类的实例能够直接訪问。子类中能够訪问。

    2. 双下划线的函数或属性,在类定义中能够调用和訪问。类的实例不能够直接訪问,子类不可訪问。

    注意:对于双下划线的函数或属性,Python解释器使用了名字混淆的方法, 将私有的方法"__method"变成了"_classname__method"了,详细看下文演示样例。



    双下划线的私有函数和属性。在子类中不可见。不存在”覆盖“

    class Base(object):
        def __private(self):
            print("private value in Base")
    
        def _protected(self):
            print("protected value in Base")
    
        def public(self):
            print("public value in Base")
            self.__private()
            self._protected()
    
    class Derived(Base):
        def __private(self):
            print("override private")
    
        def _protected(self):
            print("override protected")
    
    
    print dir(Base)
    print("="*80)
    d = Derived()
    d.public()
    d._protected()
    d._Derived__private()
    print("="*80)
    d.__private()
    
    输出结果例如以下:

    >>> 
    ['_Base__private', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_protected', 'public']
    ================================================================================
    <span style="color:#FF0000;">public value in Base
    private value in Base
    override protected</span>
    override protected
    <span style="color:#FF0000;">override private</span>
    ================================================================================
    
    Traceback (most recent call last):
      File "D:	emp	est.py", line 91, in <module>
        d.__private()
    AttributeError: 'Derived' object has no attribute '__private'
    >>> 

    注意上面输出的红色字体部分,与我们想象中的输出可能不太一样啊。调用子类的public方法时,子类的双下划线方法 __private 并没有”覆盖“父类的方法,但子类的单下划线方法_protected方法却”覆盖“了父类的方法。

    这当中的原因,就在于子类要”覆盖“父类的方法,得让子类可以具有訪问父类对应方法的权限才行。



    不要定义Python的混淆类方法名称

    Python解释器对于类(ClassName)双下划线的私有方法(__method),会进行名称混淆(Name Mangle),规则为 _ClassName__method。所以不要在类方法中同一时候存在__method和 _ClassName__method。

    演示样例

    class Base(object):
        def _secret(self):
            print("Base secret")
    
        def __hide(self):
            print("Normal __hide")
    
        def _Base__hide(self):
            print("Special _Base__hide")
    
        def public(self):
            print("From public method")
            self.__hide()
    
    print dir(Base())
    print("="*80)
    Base().public()
    输出例如以下

    [<span style="color:#FF0000;">'_Base__hide'</span>, '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_secret', 'public']
    ================================================================================
    From public method
    <span style="color:#FF0000;">Special _Base__hide</span>
    能够看出 __hide 已经被 _Base__hide方法替换掉了。外部也能够直接通过 Base()._Base__hide()方式调用(但千万别用这样的方式实现,比較混乱!)。





  • 相关阅读:
    ES6基础知识
    浏览器相关的前端知识
    JavaScript基础知识汇总
    HTML(超文本标记语言)基础知识汇总
    CSS相关基础知识汇总
    NYOJ 737 石子合并(一)
    HDU 1051 Wooden Sticks
    NY 325 zb的生日
    HDU 2068 RPG的错排
    HDU 1284 钱币兑换问题
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7124427.html
Copyright © 2020-2023  润新知