Python类私有方法的陷阱

原创 2015年07月09日 15:29:56

引言

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





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Python - 私有方法,专有方法

Python的私有方法:以'__'双划线开头,但不以双划线结尾, __privateMethod 专有方法:以双划线开头和结尾, __init__ e.g class Person: d...
  • rziqq
  • rziqq
  • 2016年06月13日 15:43
  • 236

Python 私有函数

与大多数语言一样,Python 也有私有的概念: • 私有函数不可以从它们的模块外面被调用 • 私有类方法不能够从它们的类外面被调用 • 私有属性不能够从它们的类外面被访问 与大多...

python 类的私有属性和方法

类的私有属性:__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。 在类内部的方法中使用时 self.__private_attrs。类的方法:在类地内...

Python类中的 私有变量和私有方法

python类中的私有变量和私有方法 下划线 name mangling 技术

Python类的方法或特性变为“私有”方式

Python并不直接支持私有方式,而是靠程序员自己把握在外部进行特性修改的时机。毕竟在使用对象前应该知道如何使用。但是,可以使用一些小技巧达到私有特性的效果。    为了让方法或者特性变为私有(即使从...

python对象:访问私有属性和私有方法

#coding:utf-8 class Parent: def  __init__(self,name): self.name=name self.__age=5 def __get_age(se...
  • Cindy_C
  • Cindy_C
  • 2016年12月17日 10:19
  • 1210

Python的私有函数

用两个下划线开头的函数是私有函数. 虽然说是私有的, 但是还是可以在类外引用>>> class test: def __private(): print("private"); >>> a = t...
  • xxkkff
  • xxkkff
  • 2009年08月06日 12:59
  • 4550

python 类成员的访问权限

_method1 表示是私有方法,除非定义方法的类实例,否则是访问不到的。__init__好像除外? __method1 为了和子类区分,会被认作是_className__method1.仍然还是私有...
  • crzc123
  • crzc123
  • 2015年10月30日 13:15
  • 1214

Python实现子类调用父类的方法

如下代码:class A: def __init__(self): self.namea="aaa" def funca(self): print "f...

关于python中的“保护”权限

Java中的成员变量有4中权限:public >
  • djskl
  • djskl
  • 2014年09月19日 11:20
  • 1217
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Python类私有方法的陷阱
举报原因:
原因补充:

(最多只允许输入30个字)