zoukankan      html  css  js  c++  java
  • 模块的导入和使用

    一.模块

    1.什么是模块?

      常见的场景:一个模块就是一个包含了python定义和声明的文件文件名就是模块名字加上.py的后缀

    但是其实import加载的模块分为四个通用类别:

      1使用python编写的代码(.py文件)

      2.已被编译为共享库

      3.包好一组模块的包

      4.使用c编写并链接到python解释器的内置模块

    2.为何要使用模块

      1.用别人写好的模块(内置的,第三方的):典型的拿来主义,极大的提高了开发效率

      2.使用自己写的模块(自定义的):当程序比较庞大的时候,你的项目不可能只在一个py中

      随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。

    3.如何使用模块?

      3.1.import

    示例文件:自定义模块my_module.py,文件名my_module.py,模块名my_module

    #my_module.py
    print('from the my_module.py')
    
    money = 1000
    
    def read1():
        print('my_module-->read1-->money',money)
    
    def read2():
        print('my_module-->read2 calling read1')
        read1()
    
    def change():
        global money
        money = 0

      3.1.1

    模块可以包含可执行的语句和函数的定义,这些语句的目睹是初始化模块,它们只在模块名第一次遇到导入import语句是才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下

    #demo.py
    import my_module   #只在第一次导入时才执行my_module.py内代码,此处的显示效果是只打印一次‘from the my_module.py’,当然其他的顶级代码也都被执行了,只不过没有显示效果。
    import my_module
    import my_module
    import my_module
    
    
    '''
    执行结果:
    from the my_module.py
    '''

      3.1.2

    每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当作全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突

    #测试一:money与my_module.money不冲突
    #demo.py
    import my_module
    money = 10
    print(my_module.money)
    
    '''
    执行结果:
    from the my_module.py
    1000
    #测试二:read1与my_module.read不冲突
    #demo.py
    import my_module
    def read1():
        print('======')
    my_module.read1()
    
    
    '''
    执行结果:
    from the my_module.py
    my_module-->read1-->money 1000
    '''
    #测试三:执行my_module.change()操作的全局变量money仍然是my_module中的
    #demo.py
    import my_module
    money = 1
    my_module.change()
    print(money)
    
    '''
    执行结果:
    from the my_module.py
    1
    '''

      3.1.3

    总结:首次导入模块my_module时会做三件事:

      1.为源文件(my_module模块)创建新的名称空间,在my_module中定义的函数和方法若是用到了global是访问的就是这个名称空间

      2.在新创建的命名空间中执行模块中包含的代码,见初始导入import my_module

      3.创建名字my_module来引用该名称空间

      3.1.4

    为模块名起别名。相当于m1 = 1;m2 = m1

    import my_module as sm
    print(sm.money)

      3.1.5

    在一行导入多个模块

    import sys,os,re

    3.2

    form...import...

    3.2.1

    对比import my_module,会将源文件的名称空间‘my_module’带到当前名称空间中,使用时必须是my_module.名字的方式

    而from语句相当于import,也会创建新的名称空间,但是将my_module中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了。

    from my_module import read1,read2

    这样在当前位置直接使用read1和read2就好了,执行时,仍然以my_module.py文件全局名称空间

    #测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
    #demo.py
    from my_module import read1
    money=1000
    read1()
    '''
    执行结果:
    from the my_module.py
    spam->read1->money 1000
    '''
    
    #测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
    #demo.py
    from my_module import read2
    def read1():
        print('==========')
    read2()
    
    '''
    执行结果:
    from the my_module.py
    my_module->read2 calling read1
    my_module->read1->money 1000
    '''

    如果当前有重名read1或者read2,那么会有覆盖效果。

    #测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
    #demo.py
    from my_module import read1
    def read1():
        print('==========')
    read1()
    '''
    执行结果:
    from the my_module.py
    ==========
    '''

    需要特别强调的一点是:python中的变量赋值不是一种存储操作,而只是一种绑定关系,如下:

    from my_module import money,read1
    money=100 #将当前位置的名字money绑定到了100
    print(money) #打印当前的名字
    read1() #读取my_module.py中的名字money,仍然为1000
    
    '''
    from the my_module.py
    100
    my_module->read1->money 1000
    '''

    3.2.2

    from my_module import*把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性及其差,在交互环境中导入时没有问题。

    from my_module import * #将模块my_module中所有的名字都导入到当前名称空间
    print(money)
    print(read1)
    print(read2)
    print(change)
    
    '''
    执行结果:
    from the my_module.py
    1000
    <function read1 at 0x1012e8158>
    <function read2 at 0x1012e81e0>
    <function change at 0x1012e8268>
    '''

    在my_module.py中新增一行

    __all__=['money','read1']#这样在另外一个文件中用from my_module import*就只能导入列表中规定的两个名字

    3.3把模块当作脚本执行

    我们可以通过模块的全局变量__name__来查看模块名:

    当做脚本运行:

    __name__等于'__main__'

    当做模块导入:

    __name__=模块名

    作用:用来控制.py文件在不同的应用场景下执行不同的逻辑

    if __name__ == '__main__':

    def fib(n):   
        a, b = 0, 1
        while b < n:
            print(b, end=' ')
            a, b = b, a+b
        print()
    
    if __name__ == "__main__":
        print(__name__)
        num = input('num :')
        fib(int(num))

    3.4模块搜索路径

    python解释器在启动时会加载一些模块,可以使用sys.modules查看

    在第一次导入某个模块时(比如my_module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用,如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。

    模块的查找顺序是:内存中已经加载的模块-->内置模块-->sys.path路径中包含的模块

    需要注意的是:我们自定义的模块名不应该与系统内置模块重名。

    4.绝对导入与相对导入总结

    绝对导入与相对导入
    
    # 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
    #        优点: 执行文件与被导入的模块中都可以使用
    #        缺点: 所有导入都是以sys.path为起始点,导入麻烦
    
    # 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
    #        符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
    #        优点: 导入更加简单
    #        缺点: 只能在导入包中的模块时才能使用
          #注意:
            1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
            2. attempted relative import beyond top-level package # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包

    4.软件开发规范

  • 相关阅读:
    Codeforces 1265A Beautiful String
    1039 Course List for Student (25)
    1038 Recover the Smallest Number (30)
    1037 Magic Coupon (25)
    1024 Palindromic Number (25)
    1051 Pop Sequence (25)
    1019 General Palindromic Number (20)
    1031 Hello World for U (20)
    1012 The Best Rank (25)
    1011 World Cup Betting (20)
  • 原文地址:https://www.cnblogs.com/KrisYzy/p/11196289.html
Copyright © 2011-2022 走看看