小议Python的模块和包

模块和包是比类更高一级的代码封装和复用,通过把相似的代码组织在一起使用,可以大量的减少程序的耦合。对于每个模块都有所谓的内部和外部之分,从这种角度来看,模块很像一种类,模块内部的代码属于模块的私有成员,由模块控制,对外暴露接口给外部使用。

为了方便解释,使用spyder创建一个项目,模块的引用就可以很方便的在IPython端使用。

Python的模块在首次导入(import)时,模块就会编译成字节码,也就是pyc文件(python3.2以后就统一存放在__pycache__目录下)。模块会被作为一个实例,为其内部提供一个全局名字空间,在一次的session中,无论模块的源文件是否发生变化,已经初始化后的实例都不会发生变化。先创建一个module.py文件,放入下面代码。

x = "hello world!"

def test():pass

class Test:pass 

导入模块:

import module

dir(module)
Out[2]: 
['Test',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'test',
 'x']

module.x
Out[3]: 'hello world!'

修改module文件变成:

x = "god hate you"

def test():pass

class Test:pass 

再次导入文件:

import module

module.x
Out[5]: 'hello world!'

x并没有发生变化。 所以这里牵扯到Python的热更新问题了,标准库提供了importlib.reload方法解决这个问题,但是这个方案缺点在于它并不会递归的修改成员引用(当你模块的成员被其它变量引用时,引用成员并不会发生变化)

import importlib

importlib.reload(module)
Out[9]: <module 'module' from '...\\module.py'>

module.x
Out[10]: 'god hate you'

除此之外,还可以使用__name__获得模块自身的信息。在module模块添加:

print(__name__)

运行本模块,此时__name__返回的是__main__,而直接导入module时会返回模块自身的名字。

runfile('D:/python/huaban/module.py', wdir='D:/python/huaban')
__main__

importlib.reload(module)
module

如果模块里面有些信息,不希望外部看到,可以使用__all__明确指定哪些成员允许被导入。在module.py添加:

__all__ = ["test"]

from module import *
module

dir()
Out[2]: 
[...
 'test']

这样其它的成员便被隐藏了,和类的私有成员一样,这不是真正的意义权限设置,你还是有办法可以看的到。例如:

import module

dir(module)
Out[5]: 
['Test',
 '__all__',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'test',
 'x']

我们这样就可以看到了module的所有的名字空间。

原文发布于微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文发表时间:2018-04-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏vue学习

关于vue的命名规范

2995
来自专栏小二的折腾日记

多线程

进程:是一个正在执行中的程序。 每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。 线程:就是进程中的一个独立的控制单元。 线程在控制...

521
来自专栏JavaQ

高并发编程-volatile详解

在介绍volatile之前,先简单了解一下Java内存模型。在Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏...

953
来自专栏Astropeak

Spring使用 --- 基本概念(一):DI,依赖注入

1212
来自专栏Java架构沉思录

聊聊Java动态代理(上)

前言 在之前的文章《聊聊设计模式之代理模式》中,笔者为大家介绍了代理模式,在这里简单回顾一下。代理模式的作用是提供一个代理来控制对一个对象的访问,因此我们可以...

36413
来自专栏数据结构与算法

7617:输出前k大的数

7617:输出前k大的数 查看 提交 统计 提问 总时间限制:10000ms单个测试点时间限制:1000ms内存限制:65536kB描述 给定一个数组,统计前k...

3905
来自专栏Python攻城狮

Pyramid中的request和response1.Request2.Multidict3.Response

官方API:pyramid.request、pyramid.response 和 pyramid.httpexceptions。

851
来自专栏菩提树下的杨过

利用ganymed-ssh2远程执行其它Linux机器上的shell命令

实际应用中,有时候需要从web管理界面上,远程去启动其它linux主机上的程序,利用ssh协议可以方便的满足这一需求。事实上hadoop架构中,从nn上启动dn...

28110
来自专栏ShaoYL

Protocol(协议)

4377
来自专栏H2Cloud

TCPDUMP 抓包

  写了个脚本, 用于调试服务器消息传输, 代码如下: #!/bin/bash if [ $# -eq 0 ] ; then echo "usage local...

3015

扫码关注云+社区

领取腾讯云代金券