模块
-
使用python编写的代码**(.py文件)**
-
已被编译为共享库或DLL的C或C++扩展
-
包好一组模块的包
-
使用C编写并链接到python解释器的内置模块
为何要使用模块
实现代码和功能的复用
import自定义模块my_module.py
文件名my_module.py,模块名my_module
#与main文件在同一文件下,之间新建.py文件
# my_module.py
print('from the my_module.py')
money = 100
def read1():
print('my_module->read1->money',money)
def read2():
print('my_module->read2 calling read1')
read1()
def change():
global money
money=0
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到
导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块可以import多次,为了防止你重复导入
python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句)
import my_module
import my_module
import my_module
import my_module
import sys
print(sys.modules)
# sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导
入。
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
import my_module #模块见上文
money=10
print(my_module.money) # 引用模块中所定义的变量,不与其他代码冲突
import my_module
def read1():
print('=========')
my_module.read1() # 引用模块中函数与所定义的变量
money = 1
my_module.change()
print(money) # 没有加模块前缀,仍然使用本代码中的变量
print(my_module.money) #在此代码前引用了模块中函数,打印此时模块中函数运行后的变量
运行结果
from the my_module.py
100
my_module->read1->money 100
1
0
总结:首次导入模块my_module时会做三件事:
- 为源文件(my_module模块)创建新的名称空间,在my_module中定义的函数和方法若是使用到了
global时访问的就是这个名称空间。(global的是本模块的全局,不涉及主代码全局)
-
在新创建的命名空间中执行模块中包含的代码
-
创建名字my_module来引用该命名空间
为模块名起别名,相当于m1=1;m2=m1
import my_module as mm
print(mm.money)
from the my_module.py
100
示范用法:
有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
#新建两个文件
# mysql.py
def sqlparse():
print('from mysql sqlparse')
# oracle.py
def sqlparse():
print('from oracle sqlparse')
# test.py
db_type=input('>>: ') #直接选择输入 mysql或者 oracle
if db_type == 'mysql':
import mysql as db
elif db_type == 'oracle':
import oracle as db
db.sqlparse() # 无论如何选择,之后统一用db引用
在一行导入多个模块
import sys, os, re
from … import …
对比import my_module,会将源文件的名称空间’my_module’带到当前名称空间中,使用时必须是my_module.名字的方式
而from 语句相当于import,也会创建新的名称空间,但是将my_module中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了。
from my_module import read1,read2
money = 1000
read1()
# 导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
from my_module import read1,read2
money = 1000
def read1():
print('*'*10)
read2()
# 导入的函数read2,执行时需要调用read1()是read2中的read2,仍然回到my_module.py中找read1()
from my_module import read1,read2
money = 1000
def read1():
print('*'*10)
read1()
# 导入的函数read1,被当前位置定义的read1覆盖掉了
from my_module import read1 as read
read()
# 也支持as
from the my_module.py
my_module->read1->money 100
my_module->read2 calling read1
my_module->read1->money 100
**********
my_module->read1->money 100
from my_module import *** 把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置**大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
在my_module.py中新增一行
# 哪些可以被导入,哪些不想被导入
__all__ = ['money','read1']
# 这样在另外一个文件中用from my_module import *就这能导入列表中规定的两个名字
from my_module import *
print(money)
read1()
read2()
from the my_module.py
100
my_module->read1->money 100
my_module->read2 calling read1
my_module->read1->money 100
注意:如果my_module.py中的名字前加下划线,即**_money**,则from my_module import ,则*_money不能被导入**
编写好的一个python文件可以有两种用途:
-
脚本,一个文件就是整个程序,用来被执行
-
模块,文件中存放着一堆功能,用来被导入使用
python为我们内置了全局变量 name ,
-
当文件被当做脚本执行时: name 等于’main’
-
当文件被当做模块导入时: __name__等于模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑(或者是在模块文件中测试代码)
- if name == ‘main’:
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=',')
a, b = b, a+b
print()
if __name__ == "__main__":
print(__name__)
num = input('num :')
fib(int(num))
__main__
num :2
1,1,