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:\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()方式调用(但千万别用这样的方式实现,比較混乱!)。

时间: 2024-08-05 23:40:01

Python类私有方法的陷阱的相关文章

python类及其方法

python类及其方法 一.介绍 在 Python 中,面向对象编程主要有两个主题,就是类和类实例类与实例:类与实例相互关联着:类是对象的定义,而实例是"真正的实物",它存放了类中所定义的对象的具体信息. 类有这样一些的优点: 1.类对象是多态的:也就是多种形态,这意味着我们可以对不同的类对象使用同样的操作方法,而不需要额外写代码. 2.类的封装:封装之后,可以直接调用类的对象,来操作内部的一些类方法,不需要让使用者看到代码工作的细节. 3.类的继承:类可以从其它类或者元类中继承它们的

Python中私有方法和私有属性

1.私有方法和私有属性私有方法只能在类内部被调用,不能被对象使用私有属性只能在类内部使用,不能被对象使用 私有属性只能在类内部使用,对象不能使用,但是,我们可以通过在类内部定义公有方法对私有属性进行调用或修改,然后对象在调用这个公有方法使用.###私有属性和私有方法#########在属性名和方法名前面加上 __ class Person(object): def __init__(self): # 公有属性 self.name = "李四" #私有属性 self.__age = 18

Python 类特殊方法__getitem__如何使用?

本文和大家分享的主要是python类的特殊方法__getitem__相关内容,一起来看看吧,希望对大家学习python有所帮助. 凡是在类中定义了这个__getitem__ 方法,那么它的实例对象(假定为p),可以像这样 p[key] 取值,当实例对象做p[key] 运算时,会调用类中的方法__getitem__. 先用一个夸张一点的例子来说明这个问题. 当实例对象通过[] 运算符取值时,会调用它的方法__getitem__,从上面代码中输出二个笑脸可以看出来. 一般这样用 ''' 黄哥Pyth

[有码有真相]python类私有属性等要点理解及测试示例代码

# encoding: utf-8 ''' 1. python约定类定义中"__"开头(至多一个"_"结尾)的属性为"相对"的私有属性 2. 私有属性在类及其子类定义中是"可见"的,在 其它范围正常访问是相对"不可见"的 3. 留下子类可以修改父类私有属性的口子方便debug测试等 4. 在类定义以外可以通过['_'+className+'私有属性名称']名称访问 5. 私有属性引入是避免类,实例等混淆和冲

python中函数和方法区别,以及如何给python类动态绑定方法和属性(涉及types.MethodType()和__slots__)

网上有很多同义但不同方式的说法,下面的这个说法比较让你容易理解和接受 1 与类和实例无绑定关系的function都属于函数(function): 2 与类和实例有绑定关系的function都属于方法(method). “与类和实例无绑定关系”就道出了其中的关键 我们知道python是动态的编程语言,python的类除了可以预先定义好外,还可以在执行过程中,动态地将函数绑定到类上,绑定成功后,那些函数就变成类的方法了. 定义User类 可以使用__slots__来限制绑定的属性和方法 1 user

python - 类的方法

类的方法分为:普通方法和 静态方法 两种 一.普通方法: 由对象去调用执行(方法属于类) 1.创建方法 class Province: country = "中国" def __init__(self,name): self.name = name def show(self): #普通方法,由对象去调用执行(方法属于类) print(self.name) 2.访问普通方法: 普通方法的访问需要使用对象 才能访问 obj = Province("河北") obj.s

python 类和方法(面向对象)

类和方法 name = "Jack" city = "bejing" print("my name is %S and come from %s "%(name,city)) print ("hello 51zxw") name = "harry" city = "shengzhen" print("my name is %S and come from %s "%(

python类的方法

在一个类中,可能出现三种方法,实例方法.静态方法和类方法,下面来看看三种方法的不同. 1)实例方法 实例方法的第一个参数必须是"self","self"类似于C++中的"this". 实例方法只能通过类实例进行调用,这时候"self"就代表这个类实例本身.通过"self"可以直接访问实例的属性. 例如: >>> class Student(object): ...   count = 0

Method Resolution Order – Python类的方法解析顺序

在支持多重继承的编程语言中,查找方法具体来自那个类时的基类搜索顺序通常被称为方法解析顺序(Method Resolution Order),简称MRO.(Python中查找其它属性也遵循同一规则.)对于只支持单重继承的语言,MRO十分简单:但是当考虑多重继承的情况时,MRO算法的选择非常微妙.Python先后出现三种不同的MRO:经典方式.Python2.2 新式算法.Python2.3 新式算法(也称作C3).Python 3中只保留了最后一种,即C3算法. 经典类采用了一种简单MRO机制:查