Python28_模块

什么叫模块?模块的本质也是一个.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

步骤:

  1. 在包的同一级路径下建立setup.py
  2. 将以下代码加入setup.py
from distutils.core import setup    #导入setup功能

setup(name = "假装", version = "1.0", description = "xxx", author = "假装的模块", py_modules = ["suba.aa"]     #调用setup函数,最后一个参数最重要,如果一个包里面有很多模块,你要发布哪些模块,就将那些模块的名字写在该参数列表中,但是注意,不能直接写模块的名字,必须先写包的名字。其他的参数可以省略
  1. Linux下敲python3 setup.py build命令。然后会发现多了个build文件夹,相当与将那些模块copy到build/lib文件夹下
  2. 然后敲python3 setup.py sdist。然后当前目录下就会多一个dist文件夹,里面会有一个.tar.gz的压缩文件。加入别人要使用自己制作的模块,就将该压缩文件给别人即可

使用者:

  1. `tar -zcvf 下载的模块压缩包名。此例子中,就会解压出"PKG-INFO setup.py TestMsg"两个文件和一个文件夹(ps:PKG-INFO中即为我们最开始调用setup函数时传入的相关信息)
  2. 安装:python3 setup.py install,看输入的最后一行可知道是否安装成功。安装成功后,在任何路径下都可以使用该模块

重新导入模块

如果在导入了模块后,在自己程序没有退出的前提下,别人修改了模块,那么此时自己是获取不到新功能的。如果想要使用新功能,就需要使用reload(模块名)对模块重新导入(位于importlib模块中)

模块的循环导入

这是一个非常恶心的问题...

a模块中要用到b模块的内容,于是导入了b模块,但是b模块又需要用到a模块的内容,于是b模块又导入了a模块。这就是模块的循环导入问题。会出现ImportError

因此,需要从设计者的角度进行避免。
但是笔者在实际的使用中,发现可以通过import 模块名解决,如果用from ... import ...则会报错【测试环境为pycharm】

翻外之"=="和"is"

==判断内容是否相等。is判断两者是否指向同一个地址空间。

但是对于数,如果两个数大小相同,他们即==is
ps:似乎是因为所有的数都存储在常量区,当创建了一个变量指向一个常量时,是先到常量区查找,如果查找到了,那么就指向该地址,如果找不到,则在常量区开辟一个空间存储该数,然后使变量指向该空间。

你可能感兴趣的:(Python28_模块)