Python类私有方法的陷阱

引言

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

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:\temp\test.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()方式调用(但千万别用这种方式实现,比较混乱!)。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值