模块:
在Python中,模块是代码组织的一种方式,把功能相近的函数放到一个文件中,一个文件(.py)就是一个模块(module),模块名就是文件名去掉后缀py。
模块的好处:
1.提高代码的可复用性,可维护性,一个代码写完后可以很方便的在其他项目中导入
2.解决了命名冲突,不同模块中相同的命名不会冲突
模块的调用:
一般的,模块可分为两类:自定义模块和系统的模块。
下面我们讲一下模块的调用方式:
1.import 模块名
此方式调用后并不方便,在需要使用模块里内容时,需加上前缀。例如调用时:模块名.变量名,
模块名.函数名,模块名.类
#自定义模块 calculate模块
list1 = [9,8,7,6,5,4,0]
#第一种方法
import calculate模块
#使用模块中的函数 模块名.变量 模块名.函数 模块名.类
sum = calculate模块.add(*list1) #拆包
print(sum)
#使用模块中的变量
print(calculate模块.name)
#使用模块中的类
cal = calculate模块.Calculate()
print(cal) #对象的空间
cal.test()
calculate模块.Calculate.test1() #类方法可直接调用
calculate模块.Calculate.test(cal) #对象方法需创建一个对象,借助对象来调用
被调用模块:
name = 'JSY' #变量
def add(*args):
if len(args) > 1:
sum = 0
for i in args:
sum += i
return sum
else:
print('请至少传入两个参数')
class Calculate:
def test(self):
print('正在使用Calculate!')
@classmethod
def test1(cls):
print('正在调用一个类方法')
def test():
print('__name__:',__name__)
输出:
calculate方法
39
JSY
<calculate模块.Calculate object at 0x0000019A284AEC10>
正在使用Calculate!
正在调用一个类方法
正在使用Calculate!
2.from 模块名 import 模块里的内容(变量or函数or类)
使用该方式,可仅调用模块里所需要的部分,并且在使用内容时不用加模块名的前缀
3.import 模块名 as 新模块名
该方式可以将模块重命名
4.from 模块名 import *
此方式可以调用模块里的所有内容;如果想要限制被调用的内容,可在模块里使用 __all__ = [可被获取的内容]
list1 = [9,8,7,6,5,4,0]
from calculate模块 import * #在被调用的模块中加入__all__可限制允许调用的内容
# from calculate包 import add,name #加逗号表示导入同一个包的不同部分
result = add(*list1)
print(result)
test() #不在原模块执行__name__时,会打印原模块的名字
模块内容:
# __all__ = ['name']
name = 'JSY' #变量
def add(*args):
if len(args) > 1:
sum = 0
for i in args:
sum += i
return sum
else:
print('请至少传入两个参数')
def test():
print('__name__:',__name__)
if __name__ =='__main__':
print(__name__) #__name__ ---> __main__
print('calculate方法') #当调用该模块时,执行该语句
输出:
calculate方法
39
__name__: calculate模块
注意:
1.当被调用的模块里没有使用__all__来限制被调用的内容时,可以直接调用模块里的所有内容。
2.即使 print('calculate方法') 语句在模块的最下面,但是一旦模块被调用,其内容被加载, ’calculate方法‘ 反而是最先输出的。
3.在调用该模块时,if __name__ =='__main__': 语句下的内容并没有执行。
其实,无论import或from的方式,都会将模块的内容进行加载。如果有部分内容不希望被加载调用就会用到__name__。在模块中加入语句 if __name__ == '__main__': ,可将不希望被调用的语句写在该条件中。
由于当模块本身不被调用执行时,__name__=’__main__‘ ;被其他模块调用执行时,__name__='模块名'。
模块的循环导入问题:
该问题最可能出现在大型项目上,由于有大量的.py文件,不可避免有模块之间的调用,而此时如果架构不当或者代码编写不规范,很可能出现模块间的互相导入(循环导入),那么我们应该如何避免和解决这些问题呢。
###两个模块的函数出现互相调用
(A模块)
def test():
func()
(B模块)
def func():
test()
避免循环导入:
1.重构代码(需很大成本和工作量)
2.将导入操作的语句放在函数顶部,把它的作用域限制在局部,延迟导入
该方法对于编程来说,不够优雅,故不建议使用
3.将导入操作的语句放在模块最后,可以用 from
4.将导入操作放在模块顶部,用import绝对导入方式(不用from),从package开始的绝对路径
包:
包其实就是一个 Python Package ,用来存放py文件,在包中一定有__init__.py文件,且包文件名要以字母+下划线的形式;对于一般文件夹,是用来存放非py文件的,在文件夹里建一个__init__.py文件就会把它变成包。
一个包中可以放多个模块。一般的,我们的Python项目层次为:项目 > 包 > 模块 > (类 函数 变量)
导包的方法:
1.from 包名 import 模块名
##举例##
from test_Package import models
m = models.Model('lily',123) #使用包中模块的内容
print(m)
m.show()
models模块:
class Model:
def __init__(self,username,password):
self.username = username
self.password = password
def show(self):
print(self.username,self.password)
__init__.py文件:
print('test_Package的__init__文件')
输出:
test_Package的__init__文件
<test_Package.models.Model object at 0x000001CE3457AEE0>
lily 123
可见,在导入包的时候要先加载__init__文件,打印'test_Package的__init__文件'
2.from 包名.模块名 import 模块具体内容 #该方法使用最多
3.from 包名.模块名 import *
可以在被导入的模块里,使用__all__ = [被导入的具体内容]
4.from .模块名 import 具体内容
(相对路径)导入当前包下的模块里的某些内容(易出现问题)
5.from 包名 imort *
表示该包中的内容不能完全访问仅对在__init__.py中设置的__all__允许的内容进行访问(要和from 模块名 import * 作区分)
注意:当想要导入同级包下的模块时,也应按照 from *** import *** 的格式进行,不能直接 import去导入
包的__init__文件:
当导入包的时候,默认加载调用__init__.py文件。
作用:
1.当导入包的时候,把一些初始化的函数,变量,类,定义在__init__.py文件中
2.此文件中函数,变量的访问,只需要通过包名.函数
3.在里面设置__all__ = [可以访问的模块]