美文网首页我爱编程
Python基础37-包/模块(概念及导入语法)

Python基础37-包/模块(概念及导入语法)

作者: Jacob_LJ | 来源:发表于2018-06-11 23:01 被阅读35次

    Python基础-包/模块

    1 基本概念

    • 模块:
      为了让代码更容易维护,提高代码的重用价值;
      可以将一组相关功能的代码写入一个单独的.py 文件中,供外界使用;
      这个.py 文件就可以称为一个模块;

    • 包:
      包是一个有层次的文件目录结构,它定义了由 n 个模块或 n 个子包;
      包含init.py文件目录,这个目录下一定得有这个init.py文件和其他模块或子包

    • 库:
      完成一定功能的代码集合;
      具体表现可以是一个模块,也可以是包;

    • 框架:
      从库功能角度来看,解决一个开放性问题而设计的具有一定约束性的支撑结构
      通过一个框架,可以快速实现一个问题解决的骨架;到时按照框架角色去填充,交互就可以完成一个质量好,维护性高的项目;

    2 包和模块的作用

    • 有效对程序进行功能分解和封装,方便代码的管理和维护
    • 防止同一模块内的命名重复问题

    3 创建包和模块

    • 创建一个模块
      即创建一个.py 文件即可


    • 创建一个包
      即创建一个文件夹,且应该创建一个init.py文件。(Python3.3之后创建包可以不用带上init.py)

    4 查看包或模块位置及对应 API

    import json
    
    # 查看位置
    print(json.__file__)
    
    # 查看API 内容
    print(dir(json))
    
    >>>>打印结果
    /usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py
    
    ['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']
    
    

    5 导入包/模块

    5.1 常规导入

    1. 单个导入

    import module_name or import package_name
    通过点语法定位到所需的模块文件;
    导入一个包时,会自动执行init.py 文件代码

    2. 多个导入

    文件所在位置是 Test1.py

    # Test1.py
    
    import Test2, package1.Test3, package1.package_sub1.Test4
    
    # 使用时
    print(package1.package_sub1.Test4.name)
    

    3. 导入时起别名

    • 场景一:简化资源访问前缀
    # Test1.py
    
    import package1.package_sub1.Test4 as test4
    
    # 使用时
    print(test4.name)
    

    场景二:增加程序的扩展性

    优化前
    
    if file_extension == "txt":
        import txt_parse
        txt_parse.open()
        txt_parse.read()
        txt_parse.close()
    elif file_extension == "doc"
        import doc_parse
        doc_parse.open()
        doc_parse.read()
        doc_parse.close()
    
    优化后
    
    if file_extension == "txt":
        import txt_parse as p
    elif file_extension == "doc"
        import doc_parse  as p
    
    p.open()
    p.read()
    p.close()
    

    4. 仅导入包名

    import package1
    
    • 默认不会导入任何模块
    • 解决方案:
      1. 在init文件中,再次导入需要的模块
      2. 应该以 from... import...的形式导入
    # package1 内的 __init__.py
    import package1.Test3 # 这里需要写绝对路径
    
    
    
    # Test1.py
    import package
    print(package1.Test3.name)
    
    

    5.2 from 语句导入

    1. 作用

    只导入一个模块或包种的某个部分

    2. 语法

    # 从哪里,导入哪些资源到当前位置
    from A import B[as C]
    

    注意:

    • 只能从大的地方找小的东西:A 的范围 > B 的范围
    • 按照大小顺序可以将几个资源排序:包 > 模块 > 模块资源
    • 注意面向关系:
      * 包里面只能看到模块,看不到模块资源
      * 模块里面只能看到模块资源

    3. 可能的组合为

    文件位置结构

    3.1 从包中导入模块

    • 单个
    Test1.py
    
    
    name = "Test1"
    
    from package1 import Test3
    print(Test3.name) # 直接使用模块名
    
    >>>>打印结果
    Test3
    
    • 多个
    Test1.py
    
    
    name = "Test1"
    
    from package1 import Test3, Test3_1
    
    print(Test3.name)
    print(Test3_1.name)
    
    >>>>打印结果
    Test3
    Test3_1
    
    • 起别名
    Test1.py
    
    
    name = "Test1"
    
    from package1 import Test3 as t3, Test3_1 as t3_1
    
    print(t3.name)
    print(t3_1.name)
    
    >>>>打印结果
    Test3
    Test3_1
    
    • 包有多个层级
    Test1.py
    
    
    name = "Test1"
    
    from package1.package_sub1 import Test4 as t4, Test4_1 as t4_1
    
    print(t4.name)
    print(t4_1.name)
    
    >>>>打印结果
    Test4
    Test4_1
    

    3.2 从模块中导入模块资源

    • 单个
    Test2.py
    
    name2 = "Test2"
    age2 = 2
    
    Test1.py
    
    name1 = "Test1"
    age1 = 1
    
    from Test2 import name2 # 只是导入 Test 模块中的 name 资源
    
    print(name2)
    
    >>>>打印结果
    Test2
    
    • 多个
    Test1.py
    
    
    name1 = "Test1"
    age1 = 1
    
    from Test2 import name2, age2
    
    print(name2)
    print(age2)
    
    >>>>打印结果
    Test2
    2
    
    • 起别名
    Test1.py
    
    
    name1 = "Test1"
    age1 = 1
    
    from Test2 import name2 as n2, age2
    
    print(n2)
    print(age2)
    
    >>>>打印结果
    Test2
    2
    
    • 模块有多个层级
    Test1.py
    
    name1 = "Test1"
    age1 = 1
    
    from package1.Test3 import name3, age3
    
    print(name3)
    print(age3)
    
    >>>>打印结果
    Test3
    3
    

    6 通配符*

    6.1 from 模块 import *

    1. *号代表是所有 非下划线 开头资源导入到当前位置
    2. 配合变量__all__使用
      2.1 __all__是一个列表
      2.2 其中的每个元素都是字符串__all__ = ["name", "age"]
      2.3 __all__列表内容代表到时 * 号能够匹配到的资源
    3. 慎用:因为你无法预知到时候导入哪些内容到当前位置,容易产生同名变量被覆盖的错误
    Test2.py
    
    name2 = "Test2"
    age2 = 2
    
    Test1.py
    
    
    name1 = "Test1"
    age1 = 1
    
    from  Test2 import *
    print(name2)
    print(age2)
    
    >>>>打印结果
    Test2
    2
    
    • 配合__all__使用
    Test2.py
    
    
    __all__ = ["name2"] # 进行了限制处理
    
    name2 = "Test2"
    age2 = 2
    
    Test1.py
    
    
    name1 = "Test1"
    age1 = 1
    
    from  Test2 import *
    print(name2)
    print(age2)
    
    >>>>打印结果
    Test2
    Traceback (most recent call last):
      File "/Users/xxx/Desktop/PythonProject/PackageAndModule/Test1.py", line 9, in <module>
        print(age2)
    NameError: name 'age2' is not defined
    
    • 同名变量覆盖
      正常情况
    Test2.py
    # __all__ = ["name"]
    
    name = "Test2"
    age = 2
    
    Test1.py
    
    name = "Test1"
    age = 1
    
    from  Test2 import *
    print(name)
    print(age)
    
    >>>>打印结果
    Test2
    2
    

    异常情况,同名变量被覆盖

    Test2.py
    # __all__ = ["name"]
    
    name = "Test2"
    age = 2
    
    Test1.py
    
    from Test2 import *
    
    name = "Test1"
    age = 1
    
    print(name)
    print(age)
    
    >>>>打印结果
    Test1
    1
    

    6.2 from 包 import *

    1. 基本同上,主要是导入包时,会去识别__init__.py文件内的__all__变量
    2. 此时的__all__列表内字符串元素描述的是包内模块名 __all__ = ["module1", "module2"]
    3. 使用例子:


    package1 文件夹中的 __init__.py
    
    __all__ = ["Test3"] #限制提供给外界的模块
    
    Test3.py
    
    name3 = "Test3"
    age3 = 3
    
    Test1.py
    
    name = "Test1"
    age = 1
    
    from package1 import *
    
    print(Test3.name3)
    
    >>>>打印结果
    Test1
    
    • 注意,如果package1 文件夹中的 init.py文件内没有指明__all__变量,则Test1.py 文件的代码会报错

    Question:

    1. import 和 from... import...有什么区别
    2. 模块,函数,包,类按照大小顺序排序是
    3. form A import B 中 A 和 B 的填写有什么注意事项

    相关文章

      网友评论

        本文标题:Python基础37-包/模块(概念及导入语法)

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