美文网首页
Python28_模块

Python28_模块

作者: jxvl假装 | 来源:发表于2019-09-27 12:30 被阅读0次

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

          本文链接:https://www.haomeiwen.com/subject/lrhuuctx.html