zoukankan      html  css  js  c++  java
  • Python基础(十八)

    今日主要内容

    一、包

    (一)什么是包

    • 只要是含有__init__.py文件的文件夹就是一个包
    • 包的本质其实就是一个文件夹,利用包将不同功能的模块组织起来,以此来提高程序的结构性和可维护性
    • 包是用来导入的,不是用来执行的,所以它和软件开发规范分文件管理还是有区别的,一个是项目,一个是用来导入的包
    • 正因为包是用来导入的,所以运行文件一定要放在包的外面

    (二)创建一个包

    • 利用代码创建一个包

      import os
      os.makedirs('glance/api')
      os.makedirs('glance/cmd')
      os.makedirs('glance/db')
      l = []
      l.append(open('glance/__init__.py','w'))
      l.append(open('glance/test.py','w'))
      l.append(open('glance/api/__init__.py','w'))
      l.append(open('glance/api/policy.py','w'))
      l.append(open('glance/api/versions.py','w'))
      l.append(open('glance/cmd/__init__.py','w'))
      l.append(open('glance/cmd/manage.py','w'))
      l.append(open('glance/db/models.py','w'))
      map(lambda f:f.close() ,l)
      
      • 下述所有内容,均以此图结构为基础

    (三)__init__.py文件

    • 在我们导入包的时候,其实本质上导入的就是__init__.py文件,解释器会自动执行__init__.py文件中的内容

      # glance/__init__.py
      print("这里是glance下的__init__.py文件")
      
      # run.py
      import glance
      
      运行结果:
      这里是glance下的__init__.py文件
      

    (四)包的导入

    • 包的导入,须注意两点内容:
      • 导入时无论是使用import还是使用from xxx import xxx导入,点的前面必须是一个包
      • 使用from xxx import xxx导入时,import前可以出现点,import后不能出现点
    1. 常规导入

      • import导入
      # policy.py
      def policy_func():
      	print("这是policy文件中的函数")
      	
      # run.py
      import glance.api.policy
      
      glance.api.policy.policy_func()
      
      运行结果:
      这是policy文件中的函数  # 成功导入
      
      • from import导入
      # policy.py
      def policy_func():
      	print("这是policy文件中的函数")
      	
      # run.py
      from glance.api.policy import policy_func
      
      policy_func()
      
      运行结果:
      这是policy文件中的函数  # 成功导入
      
    2. 包内部之间的导入:

      • 包内部之间的相互引用,只能用绝对导入和相对导入,不能直接导入,比如policy.py文件需要导入versions.py文件中的函数,如果直接import导入会报找不到该模块的错误

        • 包内部互相引用的时候不能直接导入
        # versions.py
        def versions_func():
            print("这是versions文件中的函数")
        
        # policy.py
        import versions  # 直接导入versions模块,在外面的run文件中运行,就无法找到versions模块
        
        def policy_func():
            versions.versions_func()
            print("这是policy文件中的函数")
            
        # run.py
        from glance.api import policy
        
        policy.policy_func()
        
        运行结果:
        ModuleNotFoundError: No module named 'versions'
        
        • 原因分析:如果直接在policy文件中运行程序,完全没有问题,因为此时policy文件的模块查找路径中包含versions模块,但是**包是用来导入的,如果在包外的run文件中导入policy模块,此时模块查找路径就变为了run文件所在的路径,所以当policy文件导入versions模块时,路径下并没有versions模块,所以找不到该模块
      • 绝对导入:

      # versions.py
      def versions_func():
          print("这是versions文件中的函数")
      
      # policy.py
      from glance.api import versions
      
      def policy_func():
          versions.versions_func()
          print("这是policy文件中的函数")
          
      # run.py
      from glance.api import policy
      
      policy.policy_func()
      
      运行结果:
      这是versions文件中的函数
      这是policy文件中的函数
      
      • 相对导入:
      # versions.py
      def versions_func():
          print("这是versions文件中的函数")
      
      # policy.py
      from . import versions
      
      def policy_func():
          versions.versions_func()
          print("这是policy文件中的函数")
          
      # run.py
      from glance.api import policy
      
      policy.policy_func()
      
      运行结果:
      这是versions文件中的函数
      这是policy文件中的函数
      
      • 只要使用了相对导入的模块,只能作为模块使用,不能作为脚本(终端中直接运行的文件成为脚本)使用,说白了就是不能直接运行
      # versions.py
      def versions_func():
          print("这是versions文件中的函数")
      
      # policy.py
      from . import versions
      
      def policy_func():
          versions.versions_func()
          print("这是policy文件中的函数")
          
      运行结果:
      ImportError: cannot import name 'versions'
      
    3. 单独导入包,并使用包内的包或模块

      • 单独导入一个包,其本质上导入的只是__init__.py文件,包中其他的文件并没有被导入
      # policy.py
      def policy_func():
          print("这是policy文件中的函数")
          
      # run.py
      import glance  # 只导入了__init__.py文件
      
      glance.api.policy.policy_func()  # 并不能使用
      
      运行结果:
      AttributeError: module 'glance' has no attribute 'policy'
      
      
      • 此时就要利用到__init__.py文件了,__init__.py文件在包中起到了交接管理的作用,可以在__init__.py文件中导入每个子文件,也可以控制其是否能被导入,所以每一个包中必须要有__init__.py文件
      # policy.py
      def policy_func():
          print("这是policy文件中的函数")
      
      # glance/__init__.py
      from . import api
      
      # glance/api/__init__.py
      from . import policy
      
      # run.py
      import glance
      
      glance.api.policy.policy_func()
      
      运行结果:
      这是policy文件中的函数
      
      
      • 直接调用模块中的方法
      # policy.py
      def policy_func():
          print("这是policy文件中的函数")
      
      # glance/__init__.py
      from .api import *
      
      # glance/api/__init__.py
      from .policy import *
      
      # run.py
      import glance
      
      glance.policy_func()
      
      运行结果:
      这是policy文件中的函数
      
      
      • 还可以通过__all__来控制模块和模块中函数的导入

        • 控制模块导入
        # glance/__init__.py
        from .api import *
        
        # glance/api/__init__.py
        __all__ = ["versions"]  # 只能导入versions,其余api下模块都不能被导入
        
        # run.py
        import glance
        
        glance.policy
        
        运行结果:
        AttributeError: module 'glance' has no attribute 'policy'
        
        
        • 控制方法导入
        # policy.py
        def policy_func():
            print("这是policy文件中的func")
            
        def policy_foo():
        	print("这是policy文件中的foo")
        	
        # glance/__init__.py
        from .api import *
        
        # glance/api/__init__.py
        from .policy import *
        __all__ = ["policy_foo"]  # 控制只能导入foo函数,其余函数都不能被导入
        
        # run.py
        import glance
        
        glance.policy_func()
        
        运行结果:
        AttributeError: module 'glance' has no attribute 'policy_func'
        
        
  • 相关阅读:
    JAVA编写的一个简单的Socket实现的HTTP响应服务器
    IPTV 质量评价方法已经不适用于 OTT TV 质量评价
    AAC规格(LC,HE,HEv2)及性能对比
    洛谷 P1572 计算分数
    洛谷 P2128 赤壁之战
    洛谷 P2818 天使的起誓
    洛谷 P3914 染色计数
    洛谷 P1193 洛谷团队训练VS传统团队训练
    洛谷 P1318 积水面积
    洛谷 P1061 Jam的计数法
  • 原文地址:https://www.cnblogs.com/tianlangdada/p/11629672.html
Copyright © 2011-2022 走看看