模块
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
当我们退出python解释器然后重新进入,我们之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
并且随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
import
#套你大象.py print('from the my_module.py') money=1000 def read1(): print('my_module->read1->money',money) def read2(): print('my_module->read2 calling read1') read1() def change(): global money money=0
以套你大象这个.py文件为例,我们在这个py文件中写下来多个变量和函数,如果这个写函数是我们经常需要用到或者平凡使用的。当我们或者别人需要再一次的用到时,就不需要再去重复的造轮子。直接调用就行。
并且模块只用导入也只能导入一次,因为在第一次导入模块时python就会把模块写入一个内存中,当再去导入时python就会先去查看这个内存里面是否有这个模块,如果有就不再导入。
模块之间独立
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突。
#测试:money与my_module.money不冲突 #demo.py import my_module money=10 print(my_module.money) ''' 执行结果: from the my_module.py '''
#测试:read1与my_module.read1不冲突 #demo.py import my_module def read1(): print('========') my_module.read1() ''' 执行结果: from the my_module.py my_module->read1->money 1000 '''
模块别名法
用法:
import 模块名 as 别名
有两中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('>>: ') if db_type == 'mysql': import mysql as db elif db_type == 'oracle': import oracle as db db.sqlparse()
我们可以看到,当我们将模块重新改为一样的名之后,我们去执行代码时,就不用再去判断该使用那个数据库。可以提高代码的扩展性。
当然我们也可以依次行再一行中导入多个模块。
例如:
1 import sys,os,re,套你大象,讨逆猴子
但是不建议这么做,如果今后的你的程序需要修改或者删除某一部分时,会非常麻烦。建议一行导入一个模块,从上到下依次:内置模块,扩展模块,自定义模块。即直观又方便。
from ....impor ....
当我们只需要一个模块中的一个变量,或者一个函数时。这个模块有非常大,这时,我们就可以使用from ....impor ....来帮助我们。
它可以帮助我们导入一个模块中我们需要的部分。但是要注意,如果导入的变量导入本地之后那么再本地你就不能再去定义个和导入变量名字一样的变量。不然会找不到你所·导入的变量。
因为python查找是是先从本地开始查找的,一旦在本地查找到就不会向下找了。就像命名空间查找global和locals一样。
如:
#测试:导入的函数read1,被当前位置定义的read1覆盖掉了 #demo.py from my_module import read1 def read1(): print('==========') read1() ''' 执行结果: from the my_module.py ========== '''
python中的变量赋值不是一种存储操作,而只是一种绑定关系。
from my_module import money,read1 money=100 #将当前位置的名字money绑定到了100 print(money) #打印当前的名字 read1() #读取my_module.py中的名字money,仍然为1000 ''' from the my_module.py my_module->read1->money 1000 '''
当然也是支持as的
1 from my_module import read1 as read
补充:
from my_module import * 把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
from my_module import * #将模块my_module中所有的名字都导入到当前名称空间 print(money) print(read1) print(read2) print(change) ''' 执行结果: from the my_module.py <function read1 at 0x1012e8158> <function read2 at 0x1012e81e0> <function change at 0x1012e8268> '''
在my_module.py中新增一行
__all__=['money','read1'] #这样在另外一个文件中用from my_module import *就这能导入列表中规定的两个名字
注意:__all__是和from 模块名 import * 配合使用的。如果all的列表里面没有变量名时才会导入全部模块,不然只导入all里面有的。
对了。还有一个点。
当我们自己写模块的时候,我们可以再模块里面使用__name__来让我们模块更加好扩展。
__name__在当前.py文件打印出来是__main__,在其他文件打开时是是模块文件的名字。因此我们可以使用if判断来实现在模块中可以运行显示出我这个模块的功能。在调用文件中调用时只能用被调用时才能执行结果。
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))