在软件的设计中,经常提及到解耦的概念,即模块和模块之间的功能尽可能独立,减少不必要的关联。所以在实际项目中,我们经常会将一个工程拆解成很多不同的功能模块,以实现更优的设计并满足团队开发的要求。
有了模块的概念,就涉及到模块之间的引用关系。
一、基本引用
在python中,创建模块就像编写任何其他Python文件一样。模块可以包含变量、函数、类等。
如同级目录下有其他的.py(python文件),则可以使用import方法进行模块的引用。
创建一个sub_test.py文件:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
CONST_TEST_VALUE = "THIS IS CONST VALUE FROM SUB MODULE."
def func_test():
print("Call sub func.")
class class_test:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print("SubClass name:", self.name)
print("SubClass age:", self.age)
创建一个main.py文件:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sub_test as sub
if __name__ == '__main__':
print(sub.CONST_TEST_VALUE)
sub.func_test()
#here, we create a sub class instance.
subinstance = sub.class_test("sub class",34)
subinstance.show()
在main.py中,我们实现了对文件sub_test.py的模块引用,并用sub作为别名。在执行方法中,依次调用了变量、函数,并实现了子模块中类的实例化。
二、高阶使用
为了在项目中达到最佳使用实践,我们还可能使用子目录的方式来创建python模块。此方式需要引用一个__init__.py文件,来表示此目录中的文件可做为python类引用。
The __init__.py file is a special Python file that is used to indicate that
the directory it is in should be treated as a Python package.
This file is executed when a package is imported and can contain initialization
code for the package, such as importing submodules, defining variables,
or executing other code
基于官方描述,__init__.py是一个特殊的python文件,用来表示这个目录应该作为一个python包/模块来对待。这个特殊的文件将在被引用的时候执行,而且可以包含模块的初始化代码。
2.1 简单使用
在main.py同级目录内,创建一个sub_folder文件夹,并创建空的__init__.py以及一个subFoler_test.py,此时目录结构如下:
main.py
sub_folder
----__init__.py
----subFolder_test.py
subFoler_test.py源码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def func_test():
print("Call subFolder func.")
修改main.py如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#sub_test.py
import sub_test as sub
#subFolder_test.py in the directory sub_folder
import sub_folder.subFolder_test as subFolder
if __name__ == '__main__':
print(sub.CONST_TEST_VALUE)
sub.func_test()
#here, we create a sub class instance.
subinstance = sub.class_test("sub class",34)
subinstance.show()
subFolder.func_test()
执行输出如下:
THIS IS CONST VALUE FROM SUB MODULE.
Call sub func.
SubClass name: sub class
SubClass age: 34
Call subFolder func.
2.2 使用__init__.py进行初始化
假设我们的包结构进一步复杂化,其结构如下:
main.py
sub_folder
----__init__.py
----subFolder_test.py
----s1.py
----s2.py
----s3.py
----s4.py
此时如果按照2.1中的方式进行引用,则引用代码需要修改如下:
import sub_folder.subFolder_test as subFolder
import sub_folder.s1
import sub_folder.s2
import sub_folder.s3
import sub_folder.s4
上述方式很显然不符合设计规范。
我们需要通过修改__init__.py文件的内容,来达到简化引用的目的。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sub_folder.subFolder_test
import sub_folder.s1
import sub_folder.s2
import sub_folder.s3
import sub_folder.s4
subFolder = sub_folder.subFolder_test
s1 = sub_folder.s1
s2 = sub_folder.s2
s3 = sub_folder.s3
s4 = sub_folder.s4
main.py同步修改,此时引用代码将大幅精简:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#sub_test.py
import sub_test as sub
#subFolder_test.py in the directory sub_folder
import sub_folder as sf
if __name__ == '__main__':
print(sub.CONST_TEST_VALUE)
sub.func_test()
#here, we create a sub class instance.
subinstance = sub.class_test("sub class",34)
subinstance.show()
sf.subFolder.func_test()
sf.s1.func_test()
sf.s2.func_test()
sf.s3.func_test()
sf.s4.func_test()
执行输出如下:
THIS IS CONST VALUE FROM SUB MODULE.
Call sub func.
SubClass name: sub class
SubClass age: 34
Call subFolder func.
Call subFolder s1 func.
Call subFolder s2 func.
Call subFolder s3 func.
Call subFolder s4 func.
三、总结
在此章节,我们总结了基于同级目录下python模块的简单引用,以及基于__init__.py的高阶使用。通过这两种方式的组合,我们将可以实现项目中的各种模块的引用。