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()方式调用(但千万别用这样的方式实现,比較混乱!)。
Python类私有方法的陷阱的更多相关文章
- python类及其方法
python类及其方法 一.介绍 在 Python 中,面向对象编程主要有两个主题,就是类和类实例类与实例:类与实例相互关联着:类是对象的定义,而实例是"真正的实物",它存放了类中 ...
- python类中方法加单下划线、双下划线、前后双下滑线的区别
首先看一段代码: class Foo(): def __init__(self): print "__init__ method" def public_method(self): ...
- Python类,域,方法,对象,继承
类和对象: 是面向对象编程的两个主要方面,类创建一个新类型,而对象这个类的实例.. 域: 属于一个对象或类的变量被称为域.域有两种类型: 属于每个实例(类的对象)或属于类本身.它们分别被称为实例变量和 ...
- python中函数和方法区别,以及如何给python类动态绑定方法和属性(涉及types.MethodType()和__slots__)
网上有很多同义但不同方式的说法,下面的这个说法比较让你容易理解和接受 与类和实例无绑定关系的function都属于函数(function): 与类和实例有绑定关系的function都属于方法(meth ...
- Python 类中方法的内部变量,命名加'self.'变成 self.xxx 和不加直接 xxx 的区别
先看两个类的方法: >>> class nc(): def __init__(self): self.name ='tester' #name变量加self >>> ...
- 第8.7节 Python类__new__方法和构造方法关系深入剖析:__new__方法执行结果对__init__的影响案例详解
一. 引言 前面章节介绍了类中的构造方法和__new__方法,并分析了二者执行的先后顺序关系.__new__方法在__init__方法前执行,__new__方法执行后才返回实例对象,也就是说__new ...
- Spring实现类私有方法测试通用方案
现实的业务场景中,可能需要对Spring的实现类的私有方法进行测试. 场景描述: 比如XXXService里有 两个函数a.函数b. 而实现类XXXServiceImpl中实现了函数a.函数b,还包含 ...
- python - 类的方法
类的方法分为:普通方法. 静态方法和类方法 调用方式 特征 普通方法 由对象去调用执行,属于类 至少一个self,对象调用 静态方法 属于类,但通过类来调用,不依赖于任何对象,方法内部不需要对象封 ...
- python 类和方法(面向对象)
类和方法 name = "Jack" city = "bejing" print("my name is %S and come from %s &q ...
随机推荐
- 华硕(ASUS)X554LP笔记本重装win7后网卡和USB驱动问题的解决
以前在其它笔记本上采用U盘克隆安装winxp系统非常顺利,各种硬件驱动能自动识别并安装. 手上有一台别人的华硕(ASUS)X554LP笔记本,原装win8.1,用不惯,想装个win7旗舰版. 照例去系 ...
- SQLState: 23000
今天登陆项目的时候,报500,日志显示如下: 解决办法是: 首先,删除序列:DROP SEQUENCE sys_log_seq 然后,新建序列:CREATE SEQUENCE sys_log_seq ...
- java.lang.RuntimeException: java.lang.NullPointerException...的错误
先FQ,让电脑能登上谷歌,然后重新安装,应该就好了,我的是这样解决的.如果下次安装又报:java.lang.RuntimeException: java.lang.NullPointerExcepti ...
- Understanding and Analyzing Application Crash Reports
Introduction When an application crashes, a crash report is created and stored on the device. Crash ...
- JavaScipt30(第二个案例)
承接上篇https://www.cnblogs.com/wangxi01/p/10641115.html,这是第二个案例 附上项目链接: https://github.com/wesbos/JavaS ...
- pringboot开启找回Run Dashboard
代码中加入 <option name="configurationTypes"> <set> <option value="SpringBo ...
- 简单了解jdbcTemplate的queryForList是如何查询
queryForList方法会调用query方法,同时会传入一个新的ColumnMapRowMapper对象 ArgumentPreparedStatementSetter对象只有一个Object[] ...
- jQuey中的return false作用是什么?
jQuey中的return false作用是什么?在众多的语句中都有return false的使用,当然对于熟悉它的开发者来说,当然是知根知底,知道此语句的作用,当然也就知道在什么时候使用此语句,不过 ...
- python之cookbook-day03
第一章:数据结构和算法 1.3 保留最后 N 个元素 问题: 在迭代操作或其他操作的时候,怎样只保留最后有限几个元素的历史记录? 解决方案: 保留有限历史记录正是 collections.deque ...
- Spring 使用注解注入 学习(四)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...