一、 引言

Python模块可以为调用者提供模块内成员的访问和调用,但某些情况下, 因为某些成员可能有特殊访问规则等原因,并不适合将模块内所有成员都提供给调用者访问,此时模块可以类似类的封装机制类似的模式提供一定的内部成员保护。

模块内的内部成员封装机制有两种,一种是定义类似类的私有成员,二是类似类的__slots__实例属性白名单机制,下面分别介绍这两种方法。

二、 定义模块的私有成员

在模块内,一个以下划线开头的成员属于模块的私有成员,在使用“from 模块名 import *”不会被导入,这和类的私有成员管理比较像,但还是有如下区别:

1、 下划线开头的成员包括了单下划线开头、双下划线开头、双下划线开头双下划线结尾的成员,它们的处理是一样的,而类中它们是不一样的,具体大家可参考《第7.8节 Python中隐秘的类封装方法》

2、 模块的私有成员使用“from 模块名 import *”这样的语句来导入模块时,程序会跳过下划线开头的模块成员,即下划线开头的所有成员都不能“from 模块名 import *”导入,但可以通过“import 模块名”或“from 模块名 import 成员”方式导入。

Python通过这种简单的名字规则来隐藏成员的方法就是模块的封装机制,可以看到其实这种封装机制很脆弱。

3、 案例:

我们定义一个imptest.py,文件内容如下:

#imptest.py
def f():
print("execute ftest function in imptest....")
def _f1():
print("execute _f1(单下划线开头) function in imptest....")
def __f2():
print("execute __f2(双下划线开头) function in imptest....")
def __f3__():
print("execute __f3__(双下划线开头结尾) function in imptest....")
print("Now in imptest module!")

1)使用“from 模块名 import *”导入并调用成员执行验证是否导入成功:

>>> from imptest import *
Now in imptest module!
>>> f()
execute ftest function in imptest....
>>> _f1()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
_f1()
NameError: name '_f1' is not defined
>>> __f2()
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
__f2()
NameError: name '__f2' is not defined
>>> __f3__()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
__f3__()
NameError: name '__f3__' is not defined
>>>

可以看到凡是带下划线的都没有导入。

2) 使用“import 模块名”导入并调用成员执行验证是否导入成功:

>>> import imptest
Now in imptest module!
>>> imptest.f()
execute ftest function in imptest....
>>> imptest._f1()
execute _f1(单下划线开头) function in imptest....
>>> imptest.__f2()
execute __f2(双下划线开头) function in imptest....
>>> imptest.__f3__()
execute __f3__(双下划线开头结尾) function in imptest....
>>>

可以看到都能正常导入使用。

本节介绍了模块中使用下划线开头定义成员能防止“from 模块名 import *”导入这些成员,这是一种Python提供的弱封装机制,但建议大家在使用时还是遵循这种机制。

老猿Python,跟老猿学Python!

博客地址:https://blog.csdn.net/LaoYuanPython


请大家多多支持,点赞、评论和加关注!谢谢!

最新文章

  1. 华为5700s配置链路聚合
  2. VBA使用的Randomize和DoEvents
  3. 封装用className选元素
  4. Modules
  5. equals() 与 hashcode() 的区别与联系
  6. java 基本数据类型 回顾
  7. NGUI-快捷键
  8. PHP设计模式笔记五:策略模式 -- Rango韩老师 http://www.imooc.com/learn/236
  9. poj1064 二分,注意精度!
  10. Ecshop中transport和jquery不兼容的解决方案
  11. [Scala] 了解 协变 与 逆变
  12. mongodb增加新字段报错解决方法
  13. .NetCore2.1 WebAPI 根据swagger.json自动生成客户端代码
  14. JavaScript中闭包的写法和作用详解
  15. 潭州课堂25班:Ph201805201 tornado 项目 第六课 用户和图片分享的集成(课堂笔记)
  16. 应用监控CAT之cat-consumer源码阅读(二)
  17. 4.5Python数据处理篇之Matplotlib系列(五)---plt.pie()饼状图
  18. postman变量的使用和设置
  19. 列表选择模式:单选、按shift、按shift或ctrl
  20. flask再学习-重构!启动!

热门文章

  1. 直播软件开发关于Android、iOS中的视频采集步骤
  2. VUE自定义(有限)库存日历插件
  3. Docker 基础 B站 学习 最强 教程
  4. C++ 数据结构 4:排序
  5. Java 实现输入公历日期输出农历日期、生肖、天干地支、节日、节气等信息
  6. ubuntu12.04 安装lamp &lt;1&gt;
  7. 各种编程语言忽略http的SSL证书认证
  8. .net core中的哪些过滤器 (Authorization篇)
  9. Linux上传递文件到另外一个Linux服务器
  10. Spring源码之Bean生命周期