前面章节已经介绍了Python中的多态和继承,本节将介绍面向对象程序设计OOP三大特征的另一个特征--封装。

一、    概念

封装是将对象的状态信息(也就是数据、属性)隐藏在对象内部,将对象的属性和实现细节隐藏起来,不允许外部程序直接访问对象内部信息,而是通过类所提供的方法来实现对内部信息的操作和访问,让方法来控制对这些属性进行安全的访问和操作。实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。

封装除了隐藏类的数据和实现细节外,可以达到如下目的:

1.    让调用方只能通过类定义的方法来访问类和对象内部的属性和数据,从而可以在相关方法里加入控制逻辑,对数据进行检查和处理,确保属性的访问符合设计者的预期; 

2.    便于修改,所有对该数据的访问都通过方法进行,开发人员只需要保证调用格式和返回数据格式保持不变就可以兼容原有的调用代码,无需修改调用方代码,提高代码的可维护性。

二、    Python封装机制

在大部分面向对象开发的语言如c++和Java语言中,封装是通过私有成员和方法实现的,而Python没有显示定义私有成员的方法,其封装是利用了变量和方法命名的特殊处理来实现的。具体来说:

1.    如果要让内部属性不被外部访问,可以把属性(含方法)的名称前加上两个下划线,在Python中,实例的变量名和方法名如果以两个下划线开头(但不能是两个下划线结尾),就变成了一个私有变量(private),只有内部可以访问,外部不能访问:

1)    Python的私有变量,直接在外部通过实例是无法访问的;

2)    Python私有变量的实现方式是,在Python编译时,对于类定义中所有以两个下划线打头(但不能是两个下划线结尾)的名称都进行转换,在开头加上一个下划线和类名;

3)    Python这种幕后处理手法,使得开发人员能通过名字变换从类和对象外访问私有属性和方法,但这种方式应该禁止,因为直接访问可能导致程序不能遵循设计和开发人员对数据的控制,导致意外的错误。

2.    在Python中,变量名类似__xxx__的,也就是以双下划线开头并且以双下划线结尾的变量和方法,是特殊变量,特殊变量是可以直接访问的,不是私有变量,所以,一般实例变量和类变量以及方法不能用__xxx__这样的方式命名;

3.    在Python中,除了双下划线开头变量是私有变量外,还有一种变量名或方法名以一个下划线开头,这样的实例变量和方法外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,请视为私有变量不要随意访问。Python对这种变量,执行from module import * 不会导入,也就是说import如果不指定导入的方法名,导入时对模块中以一个下划线打头的名称的方法不会导入。

从上所述,Python的封装与常规的OOP语言差异比较大,它没有为私有属性提供直接的支持,要让方法或属性成为私有的,只需让其名称以两个下划线打头即可。这种处理要求程序员知道在什么情况下从外部修改属性是安全的。因此Python无法禁止别人访问对象的私有方法和属性,但这种名称修改方式发出了强烈的信号,让他们不要这样做。

本节介绍了Python中类的封装机制,下节将结合一个案例详细说明。

老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。

欢迎大家批评指正,谢谢大家关注!

第7.8节 Python中隐秘的类封装方法的更多相关文章

  1. 第7.4节 Python中与众不同的类

    一.    引言 在较旧的Python版本中,类型和类之间泾渭分明:内置对象是基于类型的,而自定义对象是基于类的.因此,你可以创建类,但不能创建类型.在较新的Python 2版本中,这种差别不那么明显 ...

  2. 第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一.    引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不 ...

  3. 第7.15节 Python中classmethod定义的类方法详解

    第7.15节  Python中classmethod定义的类方法详解 类中的方法,除了实例方法外,还有两种方法,分别是类方法和静态方法.本节介绍类方法的定义和使用. 一.    类方法的定义 在类中定 ...

  4. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  5. 第7.22节 Python中使用super调用父类的方法

    第7.22节 Python中使用super调用父类的方法 前面章节很多地方都引入了super方法,这个方法就是访问超类这个类对象的.由于super方法的特殊性,本节单独谈一谈super方法. 一.su ...

  6. 第8.23节 Python中使用sort/sorted排序与“富比较”方法的关系分析

    一. 引言 <第8.21节 Python中__lt__.gt__等 "富比较"("rich comparison")方法用途探究>和<第8.2 ...

  7. 第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析

    一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...

  8. 第11.20节 Python 中正则表达式的扩展功能:后视断言、后视取反

    一. 引言 在<第11.19节 Python 中正则表达式的扩展功能:前视断言和前视取反>中老猿介绍了前视断言和前视取反,与二者对应的还有后视断言和后视取反. 二. (?<=-)后视 ...

  9. 第14.12节 Python中使用BeautifulSoup解析http报文:使用select方法快速定位内容

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>和<第14.11节 Python中使用BeautifulSo ...

随机推荐

  1. 【QT】子类化QObject+moveToThread实现多线程

    往期链接: <QThread源码浅析> <子类化QThread实现多线程> 从往期<QThread源码浅析>可知,在Qt4.4之前,run 是纯虚函数,必须子类化Q ...

  2. 【SpringBoot】08.SpringBoot整合jsp

    SpringBoot整合jsp 1.修改pom文件加入两个坐标jstl标签库和jasper <project xmlns="http://maven.apache.org/POM/4. ...

  3. C# 集合类(二)

    C# 集合类自己经常用到: 数组(Array).动态数组(ArrayList).列表(List).哈希表(Hashtable).字典(Dictionary),对于经常使用的这些数据结构,做一个总结,便 ...

  4. linux下的终端利器----tmux

    转:tmux 是指通过一个终端登录远程主机并运行后,在其中可以开启多个控制台的终端复用软件.类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远 ...

  5. 9 HTTP和HTTPS

    9 HTTP和HTTPS 状态码 定义 1xx 报告 接收到请求,继续进程 2xx 成功 步骤成功接收,被理解,并被接受 3xx 重定向 为了完成请求,必须采取进一步措施 4xx 客户端出错 请求包括 ...

  6. Manacher (马拉车) 算法:解决最长回文子串的利器

    最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...

  7. CORS与Django

    前言 在前后端分离项目中,如何解决跨域请求是一个必须要面对的问题.因为前端和后端的数据交互会被浏览器的同源策略所挟持,在很早之前我在博客园发了一篇文章,大概就说了一下如何简单粗暴的解决跨域. 其实那种 ...

  8. SpringBoot魔法堂:说说带智能提示的spring-boot-starter

    前言 前几个月和隔壁组的老王闲聊,他说项目的供应商离职率居高不下,最近还有开发刚接手ESB订阅发布接口才两周就提出离职,而他能做的就只有苦笑和默默地接过这个烂摊子了. 而然幸福的家庭总是相似的,而不幸 ...

  9. Go语言内存分配(简述 转)

    在Go语言里,从内存的分配到不再使用后内存的回收等等这些内存管理工作都是由Go在底层完成的.虽然开发者在写代码时不必过度关心内存从分配到回收这个过程,但是Go的内存分配策略里有不少有意思的设计,通过了 ...

  10. 验证rbd的缓存是否开启

    简单快速的在客户端验证rbd的cache是否开启 首先修改配置文件 在ceph.conf中添加: [client] rbd cache = true rbd cache writethrough un ...