什么叫模块?模块的本质也是一个.py文件,里面通常是一些定义好的类、方法等
模块
# 法一:
import 模块名
# 这个过程python解释器做了两个工作
# 1. python解释器加载该模块
# 2. 在本模块中定义了名字与导入的模块名相同的变量,使之指向导入的模块
模块名.方法名 () #使用方法
# 法二:
from 模块名 import 方法名或类名
方法名() #使用方法
# 法三:从一个模块导入多个方法或类:
from 模块名 import 方法1,方法2
方法1()
方法2() #使用方法
# 法四:导入模块中所有内容
from 模块名 import * #尽量少使用,避免导入同名的内容
方法名() #使用方法
# 法五:起别名。场景:模块名过长时
import 模块名 as 别名
# 这个过程python解释器做了两个工作
# 1. python解释器加载该模块
# 2. 在本模块中定义了一个名字为别名的变量,使之指向导入的模块
别名.方法() #使用方法,如果使用"模块名.方法()"就会出错,因为没有aa这个变量
sys.path
sys模块中的paht存储了模块的路径(类型为列表),导入模块时就到这里的路径中去查找,如果查找不到,就报错。ps:其中的空字符串表示当前路径
即,我们可以通过insert或append自己添加模块的路径
注意事项:如果导入了名字相同的内容,先导入的会被后导入的覆盖
导入模块时,先搜索当前路径,如果当前路径没有该模块,再到系统路径去搜索
模块的作用: 1、解耦。2、便于团队协作编程(不同的人做不同的工作)
ps:一般整个程序最核心的py命名为main.py
实际上导入模块的时候,会把整个模块执行一遍
#这里是a.py
def test1():
pass
print(__name__) #ps:__name__代表模块的名字,如果是自己执行,输出__main__,如果是模块被别人调用,则输出模块名
#这里是b.py
import a #由于导入模块会把整个模块执行一遍,所以如果在这里执行b.py,则会输出__a__
__name__有一个很独特的功能,如果是自己调用,为"__main__",如果是别人导入使用,为"__模块名__"
则在自己调试程序时,可以采用如下方法,以避免在main调用时输出自己调试时的输出内容:
#这里是a.py
def test1():
pass
if __name == "__main__":
test1() #在if语句内写调试功能,则在main函数调用时,由于__name__ == "__a__"而不会被执行
#这里是b.py
import a #由于导入模块会把整个模块执行一遍,所以如果在这里执行b.py,则会输出__a__
在以后些程序,通常结构如下:
import xxx
class ClassName(object):
"""docstri
"""
pass
def xxx():
pass
def main(): #有经验的人通常用main来表示整个程序开始的地方
pass
if __name__ == "__main__": #则在自己调试时,下面内容会执行,如果别人要用到这这个模块里面定义的类、方法等而导入此模块,下面的内容不会被执行
main()
__all__
在模块的最开头写上__all__=["函数名1(不包括括号,用字符串引起来)","函数名2","类名","全局变量名"]
让别人可以通过from 模块名 import *
方式使用该列表中的函数、类或全局变量。即让别人可以通过import *
的方式导入
包
包:包含多个功能相关的py文件的文件夹,并且该文件夹下含有"init.py"文件。只有对于含"__init__.py"文件的文件夹,python解释器才将其看作包。
#当前目录结构(假设在当前目录下):./infordisplay.py ./TestMsg/__init__.py ./TestMsg/.recvmsg.py ./TestMsg/.sendmsg.py
#在python3中,可以通过
import TestMsg
#将该文件夹导入,但是如果没有__init__.py文件的话,该文件夹里面的模块无法被使用。对于python3,有没有__init__.py并无太大影响(习惯写上)。但是对于python2,如果没有该文件,python解释器只能将其看作普通文件夹,不能将其看做包导入,有了之后才能看做包,进而导入。
#如果在__init__.py文件里面写上:
__all__ = ["包里面的模块名1(不包含.py)","包里面的模块名2"]
#则其他py文件在用import 文件夹(包)名后,就可以使用模块1和模块2里面的东西
__all__ = []
小结:如果是在在模块里面,影响以后通过" * "方式导入时能够导入哪些东西。如果是在包的__init__.py
文件里面,影响的是以后能够从包里面导入哪些模块。**实际上在导入包的时候,要首先执行__init__.py
文件里面的功能(类似于模块的导入)
对于python2
#__init__.py文件内容
__all__ = ["sendmsg"] #只是影响以后可以从包里面导入哪些功能
import sendmsg #与上一句没有关系,在有了上一句之后,由于导入包,__init__.py文件(即此文件)里面的内容会被执行。所以通过此法实现在导包的时候直接导入模块,以后在导入包之后就可以直接写包里面的模块
#此法对于python3不行
以上问题的通用解决方法
将__init__.py
文件的中的导入语句改为from . import sendmsg
,则python2和python3都能用
模块的发布、安装
导入模块时,先到当前目录下查找,如果当前目录下不存在,再到系统路径里面查找。如果系统路径里面都还查找不到,则报错
Q:如何让能够在任何地方都可以调包?
A:将包加入系统路径
假设当前目录内容:
.
./setup.py
./suba/aa.py
./suba/bb.py
./suba/init.py
./subb/cc.py
./subb/dd.py
./subb/init.py
步骤:
- 在包的同一级路径下建立setup.py
- 将以下代码加入setup.py
from distutils.core import setup #导入setup功能
setup(name = "假装", version = "1.0", description = "xxx", author = "假装的模块", py_modules = ["suba.aa"] #调用setup函数,最后一个参数最重要,如果一个包里面有很多模块,你要发布哪些模块,就将那些模块的名字写在该参数列表中,但是注意,不能直接写模块的名字,必须先写包的名字。其他的参数可以省略
- Linux下敲
python3 setup.py build
命令。然后会发现多了个build文件夹,相当与将那些模块copy到build/lib文件夹下 - 然后敲
python3 setup.py sdist
。然后当前目录下就会多一个dist文件夹,里面会有一个.tar.gz的压缩文件。加入别人要使用自己制作的模块,就将该压缩文件给别人即可
使用者:
- `tar -zcvf 下载的模块压缩包名。此例子中,就会解压出"PKG-INFO setup.py TestMsg"两个文件和一个文件夹(ps:PKG-INFO中即为我们最开始调用setup函数时传入的相关信息)
- 安装:
python3 setup.py install
,看输入的最后一行可知道是否安装成功。安装成功后,在任何路径下都可以使用该模块
重新导入模块
如果在导入了模块后,在自己程序没有退出的前提下,别人修改了模块,那么此时自己是获取不到新功能的。如果想要使用新功能,就需要使用reload(模块名)
对模块重新导入(位于importlib模块中)
模块的循环导入
这是一个非常恶心的问题...
a模块中要用到b模块的内容,于是导入了b模块,但是b模块又需要用到a模块的内容,于是b模块又导入了a模块。这就是模块的循环导入问题。会出现ImportError
因此,需要从设计者的角度进行避免。
但是笔者在实际的使用中,发现可以通过import 模块名
解决,如果用from ... import ...
则会报错【测试环境为pycharm】
翻外之"=="和"is"
==
判断内容是否相等。is
判断两者是否指向同一个地址空间。
但是对于数,如果两个数大小相同,他们即==
又is
ps:似乎是因为所有的数都存储在常量区,当创建了一个变量指向一个常量时,是先到常量区查找,如果查找到了,那么就指向该地址,如果找不到,则在常量区开辟一个空间存储该数,然后使变量指向该空间。