zoukankan      html  css  js  c++  java
  • 模块和包

    1.什么是模块

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

      其实import加载的模块分别为死歌通用类别:

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

        2.已被编译为共享库或DLL的C或C++扩展

        3.包好一组模块的包

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

    2.如何自己写一个模块

        创建一个py文件,给它起一个符合变量命名规则的名字,这个名字就是模块名

    3.模块的导入

      导入一个模块就是执行一个模块

      模块导入的过程中发生了什么:

        1.找到这个模块

        2.判断这个模块是否被导入过了

        3.如果没有被导入过:

          创建一个属于这个模块的命名空间

          让模块的名字指向这个空间

          执行这个模块中的代码

      给模块起别名:起了别名之后,就只能使用这个模块的别名引用变量了

      导入多个模块:

        import os,time

      规范建议:

        模块应该一个一个的导入:

          内置模块

          扩展(第三方)模块

          自定义模块

      from  import  

        模块导入的过程中发生了什么:

          1.找到要被导入的模块

          2.判断这个模块是否被导入过

          3.如果这个模块没被导入过

            创建一个属于这个模块的命名空间

            执行这个文件

            找到要导入的变量

            给导入的变量创建一个引用,指向要导入的变量

     1 #测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
     2 #demo.py
     3 from my_module import read1
     4 money = 1000
     5 read1()
     6 
     7 #测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
     8 #demp.py
     9 from my_module import read2()
    10 def read1():
    11     print("1")
    12 read2()

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

    1 #测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
    2 #demo.py
    3 from my_module import read1
    4 def read1():
    5     print("1")
    6 read1()
    7 执行结果:
    8 from the my_module.py
    9 1

    from my_module import *把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置

    from my_module import *
    print(money)
    print(read1)
    print(read2)
    
    执行结果:
    from the my_module.py
    1000

    如果my_module.py中的名字前加_,即_money,则frommy_module import *,_money不能被导入

    模块引用中的情况:模块之间不允许循环引用

    4.模块的加载与修改

      每个模块只被导入一次,放入到sys.modules中,如果改变了模块中的内容,必须重启程序

    5.把模块当成脚本来使用

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

        当做脚本运行:

          __name__等于'__main__'

        当做模块导入:

          __name = 模块名

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

      if __name__ == '__main__':

     1 def fib(n):
     2     a,b = 0,1
     3     while b<n:
     4         print(b,end = '')
     5         a, b = b, a+b
     6     print()
     7 
     8 if __name__ == "__main__":
     9     print(__name__)
    10     num = input("num:")
    11     fib(int(num))

    py文件:直接运行这个文件,这个文件就是一个脚本

        导入这个文件,这个文件就是一个模块

    当一个py文件:

      当做一个脚本的时候:能够独立的提供一个功能,能自主完成交互

      当成一个模块的时候,能够被导入这调用这个功能,不能自主交互

    一个文件中的__name__变量:

      当这个文件被当做脚本执行的时候:__name__ == '__main__'

      当这个文件被当做模块导入的时候:__name__ == '模块的名字'

    6.模块搜索路径

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

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

    7.包

      1.文件夹中有一个__init__.py文件

      2.是几个模块的集合

      3.无论是import形式还是from..import形式,凡是在导入语句中(而不是在使用时)遇到带点的,这是关于包才有的导入语法

      4.包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

      5.import导入文件时,产生名称空间中的名字来源于文件,import包产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件

      6.导入一个包相当于执行了这个包下面的__init__.py文件

    关于包相关的导入语句也分为import和from..import..两种,但无论是哪种,在什么位置,都遵循一个原则:

          凡是在导入时带点的,点的左边都必须是一个包

    对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(他们都可以用点的方式调用自己的属性)

    绝对导入:

      在执行一个py脚本的时候,这个脚本以及这个脚本同级的模块中只能用绝对导入

      缺点:

        所有的导入都要从一个根目录下往后解释文件夹之间的关系

        如果当前导入包的文件和被导入的包的位置关系发生了变化,那么所有的init文件都要做相应的调整

    1 import glance
    2 glance.__init__.py
    3 import api
    4 sys.path = [path]
    5 glance.api.policy.get()

    相对导入:

      不需要去反复的修改路径

      只要一个包中的所有文件夹和文件的相对位置不发生改变,init文件就不需要调整

      不需要去关心当前这个包和被执行的文件之间的层级关系

      缺点:

        含有相对导入的py文件不能被直接执行

        必须放在包中被导入的调用才能正常的使用

    如果只是从包中导入模块的话,就不需要做任何多余的操作

    如果希望导入包的时候,能够顺便的把模块也导入进来,需要设计init文件夹

  • 相关阅读:
    Android随笔
    Android随笔
    阅读笔记
    Android随笔
    Android随笔
    Android随笔
    Android随笔
    Java随笔
    Android随笔
    NC20265 着色方案(dp)
  • 原文地址:https://www.cnblogs.com/s593941/p/9525704.html
Copyright © 2011-2022 走看看