1 私有属性的使用方式

在python中,没有类似private之类的关键字来声明私有方法或属性。若要声明其私有属性,语法规则为:

属性前加双下划线,属性后不加(双)下划线,如将属性name私有化,则 __name 即可。

(实际上,属性前加单下划线,属性后不加下划线也可以 _name )


1)以一个下划线开头的标识符(_xxx),不能访问的方法或属性,但可通过类提供的接口进行访问, 不会被语句 from module import * 语句加载。

  单下划线开头的方式或属性:弱”内部使用“标识,如:”from M import *”,将不导入所有以下划线开头的对象,包括包、模块、成员

  只是为了避免与python关键字的命名冲突

2)以两个下划线开头的标识符(__xxx),不能被外部访问的方法或属性,不会被语句 from module import * 语句加载,外部访问时会报错。

  双下划线开头的方法或属性:模块内的成员,表示私有成员,外部无法直接调用


  1. def hello1():
  2. pass
  3.  
  4. def _hello2():
  5. pass
  6.  
  7. def __hello3():
  8. pass
  9.  
  10. name1 = "name1"
  11. _name2 = "name2"
  12. __name3 = "name3"
  13.  
  14. print("该模块已被加载!")

在交互模式下运行

  1. >>> from test import *
  2. 该模块已被加载!
  3. >>> dir()
  4. ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
  5.  
  6. 'hello1', 'name1']

可知,仅加载了 hello1 方法、 name1 属性

实际上,这种方式并不是真正私有,而是”伪私有“,也即伪私有属性;

它是通过变量名压缩(mangling)来实现变量名局部化。变量名压缩的规则:在初始的变量名头部加一个下划线,再加上类的名称,最后是初始变量名的名称。

2 为什么是伪私有属性

  1. class Action(object):
  2. def __func(self):
  3. pass
  4.  
  5. if __name__ == '__main__':
  6. print(Action.__dict__)

类 Action 中有私有方法 __func 。

代码运行

  1. {'__dict__': <attribute '__dict__' of 'Action' objects>, '_Action__func': <function Action.__func at 0x7f2f6b102c80>,'__module__': '__main__', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Action' objects>}

通过类的__dict__属性类class Action 的所有属性打印出来,发现原定义的私有属性(方法)__func不存在,而是以_Action__func的形式存在于类中,也即方法__func变量名被压缩;,会自动进行扩展,从而包含所在类的名称。我们可以通过_Action__func来调用该类中的方法,这就是所谓的伪私有属性

通过修改调用形式就可以实现私有属性的外部调用:

  1. class Action(object):
  2. def __func(self):
  3. print("__func私有方法被调用")
  4.  
  5. if __name__ == '__main__':
  6. a = Action()
  7. a._Action__func()
  8. print("----------------------")
  9. b = Action()
  10. b.__func()

运行

  1. __func私有方法被调用
  2. ----------------------
  3. Traceback (most recent call last):
  4. File "test.py", line 10, in <module>
  5. b.__func()
  6. AttributeError: 'Action' object has no attribute '__func'

3  伪私有属性的意义

Python之所以支持变量名压缩(mangling),让类内部某些属性和函数局部化,使方法或属性无法在外部访问。这是因为私有属性被自动扩展为含有所在类的名称。

__membername 被系统替换成了 _classname__membername 外部使用原来的私有成员的名字时,会提示找不到。

伪私有属性是为了缓和与实例属性存储方式有关的问题。在Python中,所有实例的属性都会在类树底部的单个实例对象中。

在Python的类方法中,每当方法赋值self的属性时(如self.attr = value),就会在该实例内修改或创建该属性(继承搜索只发生在引用时,而不是赋值时)。

即使在这个层次中有多个相同的类赋值属性,也是如此。因此有可能发生冲突。

伪私有属性在较大的框架和工具中非常有用,既避免引入可能在类树中某处偶然隐藏定义的新的方法名,也可以减少内部方法被树的较低处的名称替代的机会。

如果一个属性或方法倾向于只在一个类中使用,在前面使用双下划线,一确保不受到继承树中其它名称的干扰,尤其是在多继承的环境中。

简而言之:使用伪私有属性可以解决变量名相互覆盖问题,也即  使用伪私有属性是为了避免在类树中,多个类赋值相同的属性引发冲突问题。

示例

假设有两个类,C1 和 C2,他们都有相同的属性X。

类C1

  1. class C1():
  2. def meth1(self):
  3. self.x = 'Hello World'
  4. def meth2(self):
  5. print(self.x)
  6. c1 = C1()
  7. c1.meth1()
  8. c1.meth2()

类C2

  1. class C2():
  2. def meth3(self):
  3. self.x = 'Hello Python'
  4. def meth4(self):
  5. print(self.x)
  6. c2 = C2()
  7. c2.meth3()
  8. c2.meth4()

类C1和C2在单独调用时,均能符合预期地输出

调用meth2方法时,打印meth1的赋值结果;

调用meth4方法时,打印meth3的赋值结果。

此时增加一个新的类C3,继承自C1、C2(多重继承):

  1. class C1():
  2. def meth1(self):
  3. self.x = 'Hello World'
  4. def meth2(self):
  5. print(self.x)
  6.  
  7. class C2():
  8. def meth3(self):
  9. self.x = 'Hello Python'
  10. def meth4(self):
  11. print(self.x)
  12.  
  13. class C3(C1, C2):
  14. pass
  15.  
  16. c3 = C3()
  17. c3.meth1()
  18. c3.meth3()
  19. c3.meth2()
  20. c3.meth4()

从运行结果可以看出,每次 print(self.x)的内容,取决于 self.x 最后一次赋值的内容。存在赋值覆盖问题

  1. Hello Python
  2. Hello Python

在使用伪私有属性后可以解决变量名self.x相互覆盖的问题(因为self.__x 被压缩成了 self._C1__x 和 self._C2__x,变量名不同,不会互相覆盖):

  1. class C1():
  2. def meth1(self):
  3. self.__x = 'Hello World'
  4. def meth2(self):
  5. print(self.__x)
  6.  
  7. class C2():
  8. def meth3(self):
  9. self.__x = 'Hello Python'
  10. def meth4(self):
  11. print(self.__x)
  12.  
  13. class C3(C1, C2):
  14. pass
  15.  
  16. c3 = C3()
  17. c3.meth1()
  18. c3.meth3()
  19. c3.meth2()
  20. c3.meth4()

运行结果符合C1的设计初衷:调用meth2时应该打印出meth1的赋值结果:

  1. Hello World
  2. Hello Python

参考:Python的伪私有属性    Python高级特性:私有属性

python学习笔记013——模块中的私有属性的更多相关文章

  1. python学习笔记013——模块

    1 模块module 1.1 模块是什么 模块是包含一系列的变量,函数,类等程序组 模块通常是一个文件,以.py结尾 1.2 模块的作用 1. 让一些相关的函数,变量,类等有逻辑的组织在一起,使逻辑更 ...

  2. 我的Python学习笔记(三):私有变量

    一.私有变量的定义 在Python中,有以下几种方式来定义变量: xx:公有变量 _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入 ...

  3. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  4. Python学习笔记之模块与包

    一.模块 1.模块的概念 模块这一概念很大程度上是为了解决代码的可重用性而出现的,其实这一概念并没有多复杂,简单来说不过是一个后缀为 .py 的 Python 文件而已 例如,我在某个工作中经常需要打 ...

  5. Python学习笔记—itertools模块

    这篇是看wklken的<Python进阶-Itertools模块小结> 学习itertools模块的学习笔记 在看itertools中各函数的源代码时,刚开始还比较轻松,但后面看起来就比较 ...

  6. Python学习笔记011_模块_标准库_第三方库的安装

    容器 -> 数据的封装 函数 -> 语句的封装 类 -> 方法和属性的封装 模块 -> 模块就是程序 , 保存每个.py文件 # 创建了一个hello.py的文件,它的内容如下 ...

  7. python学习笔记_week5_模块

    模块 一.定义: 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能), 本质就是.py结尾的python文件(文件名:test.py,对应模块名:test) 包:用来从逻辑上 ...

  8. python学习笔记(八)-模块

    大型python程序以模块和包的形式组织.python标准库中包含大量的模块.一个python文件就是一个模块.1.标准模块 python自带的,不需要你安装的2.第三方模块 需要安装,别人提供的. ...

  9. Python学习笔记-常用模块

    1.python模块 如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失.因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作 ...

随机推荐

  1. Adapter 适配器模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. POJ2762 Going from u to v or from v to u? 强连通+缩点

    题目链接: poj2762 题意: 给出一幅单向图.问这张图是否满足   随意两点ab 都能 从a到达b 或  从b到达a 题解思路: 推断一幅图是否满足弱连通 首先想到的是将图中的 强连通分量(能互 ...

  3. Error Lookup工具

    GetLastError()获取到的错误代码,可以通过VS2013自带的Error Lookup工具来查询错误的描述.

  4. 【nodejs】理想论坛帖子下载爬虫1.06

    //====================================================== // 理想论坛帖子下载爬虫1.06 // 循环改成了递归,但最多下载千余文件就崩了 / ...

  5. PHP经典项目案例-(一)博客管理系统5

    本篇实现发表博客. 八.发表博客 (1).界面实现file.php <tr>      <td colSpan=3 valign="baseline" style ...

  6. C#.NET常见问题(FAQ)-如何引用定义好的dll文件

    1 添加引用,找到dll文件   2 引用类的名称空间,生成类的实例,调用类的方法,测试OK.     更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com ...

  7. ZH奶酪:IBG项目工作内容

    IBG项目技术概览 (HTML/CSS/JavaScript/AngularJS/PHP/MySQL): (1)后台:PHP Yii2.0 Framework (2)前端:Ionic Framewor ...

  8. PHP 自学之路-----XML编程(Dom技术)

    上一节,讲了Xml文件基本语法及元素,实体及Dtd约束技术,下面就正式进入PHP的Xml编程 使用PHP技术对Xml文件进行操作 常用的有以下三种技术: 1.PHP dom 2.PHP结合XPath操 ...

  9. Java从零开始学十二(构造方法)

    一.构造方法 构造方法的主要目的是为类中的属性初始化 二.构造方法的定义格式 class 类名称{ 访问权限 类名称(类型1 参数1,类型2 参数2,…){ 程序语句 ; …    // 构造方法没有 ...

  10. jQuery(一)引入

    一.jQuery简介 jQuery是一个兼容多浏览器的javascript库,核心理念是write less,do more(写得更少,做得更多) 二.安装 2.1.下载 下载地址:http://jq ...