天天看點

Python 包管理1. 子產品2. 子產品的搜尋路徑和存儲包命名空間

1. 子產品

  • 一個子產品就是一個包含python代碼的檔案,字尾名稱是.py就可以,子產品就是個python檔案
  • 為什麼我們用子產品
    • 程式太大,編寫維護非常不友善,需要拆分
    • 子產品可以增加代碼重複利用的方法
    • 當作命名空間使用,避免命名沖突
  • 如何定義子產品
    • 子產品就是一個普通檔案,是以任何代碼可以直接書寫
    • 不過根據子產品的規範,最好在本塊中編寫以下内容
      - 函數(單一功能)
      - 類(相似功能的組合,或者類似業務子產品)
      - 測試代碼
                 
  • 如何使用子產品
    • 子產品直接導入
      - 子產品名稱直接以數字開頭,需要借助importlib幫助           
    • 文法
      import module_name
      module_name.function_name
      module_name.class_name           
    • 案例 01.py,02.py,p01.py,p02.py
      # 案例 01.py
          # 包含一個學生類
          # 一個sayHello函數
          # 一個列印語句
      
          class Student():
              def __init__(self, name = "NoName", age = 18):
                  self.name = name
                  self.age = age
          
              def say(self):
                      print("My name is {0}".format(self.name))
          
          def sayHello():
              print("Hi, ")
          
          print("我是子產品p0")
                     
      # 案例 02.py
          # 借助于importlib包可以實作導入以數字開頭的子產品名稱
          import importlib
          
          # 相當于導入了一個叫01的子產品并把導入子產品指派給了a
          
          a = importlib.import_module("01")
          stu = a.Student()
          stu.say()           
      # 案例 p01.py
          # 包含一個學生類
          # 一個sayHello函數
          # 一個列印語句
          
          class Student():
              def __init__(self, name = "NoName", age = 18):
                  self.name = name
                  self.age = age
          
              def say(self):
                      print("My name is {0}".format(self.name))
          
          def sayHello():
              print("Hi, ")
          
          # 此判斷語句建議一直作為程式的入口
          if __name__ == '__main__':
              print("我是子產品p01")           
      # 案例 p02.py
          import p01
          
          stu = p01.Student("xiaojing", 19)
          
          stu.say()
          
          p01.sayHello()           
      My name is xiaojing
          Hi,            
    • import 子產品 as 别名
      - 導入的同時給子產品起一個别名
      - 其餘用法跟第一種相同
      - 案例 p03.py
                 
      # 案例 p03.py
          import p01 as p
          
          stu = p.Student("yueyue", 18)
          stu.say()           
      My name is yueyue           
    • from module_name import func_name, class_name
      - 按上述方法有選擇性的導入
      - 使用的時候可以直接使用導入的内容,不需要字首
      - 案例 p04
                 
      # 案例 p04.py
          from p01 import Student, sayHello
          
          stu = Student()
          
          stu.say()
          
          sayHello()           
      My name is NoName
        Hi,               
    • from module_name import *
      - 導入子產品所有内容
      - 案例 p05.py
                 
      # 案例 p05.py
          from p01 import *
          
          sayHello()
          
          stu = Student("yaona", 20)
          stu.say()           
      Hi, 
          My name is yaona           
  • if __name__ ==

    `__main__` 的使用
    • 可以有效的避免子產品代碼被導入的時候被動執行的問題
    • 建議所有程式的入口都以此代碼為入口

2. 子產品的搜尋路徑和存儲

  • 什麼是子產品的搜尋路徑
    • 加載子產品的時候,系統會在哪些地方尋找此子產品
  • 系統預設的子產品搜尋路徑
    import sys
    sys.path  屬性可以擷取路徑清單
    # 案例 p06.py
               
    # 案例 p06.py
        import sys
        
        print(type(sys.path))
        print(sys.path)
        
        for p in sys.path:
            print(p)           
    <class 'list'>
        ['D:\\python\\project\\包管理', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\pydev', 'D:\\python\\project', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\third_party\\thriftpy', 'D:\\PyCharm Community Edition 2019.1.1\\helpers\\pydev', 'C:\\Users\\user\\.PyCharmCE2019.1\\system\\cythonExtensions', 'D:\\python\\project\\包管理', 'D:\\Anaconda3\\envs\\opp\\python37.zip', 'D:\\Anaconda3\\envs\\opp\\DLLs', 'D:\\Anaconda3\\envs\\opp\\lib', 'D:\\Anaconda3\\envs\\opp', 'D:\\Anaconda3\\envs\\opp\\lib\\site-packages']
        D:\python\project\包管理
        D:\PyCharm Community Edition 2019.1.1\helpers\pydev
        D:\python\project
        D:\PyCharm Community Edition 2019.1.1\helpers\third_party\thriftpy
        D:\PyCharm Community Edition 2019.1.1\helpers\pydev
        C:\Users\user\.PyCharmCE2019.1\system\cythonExtensions
        D:\python\project\包管理
        D:\Anaconda3\envs\opp\python37.zip
        D:\Anaconda3\envs\opp\DLLs    
        D:\Anaconda3\envs\opp\lib
        D:\Anaconda3\envs\opp
        D:\Anaconda3\envs\opp\lib\site-packages
               
  • 添加搜尋路徑
    sys.path.append(dir)           
  • 子產品的加載順序
    1. 搜尋記憶體中已經加載好的子產品
    2. 搜尋python的内置子產品
    3. 搜尋sys.path路徑

  • 包是一種組織管理代碼的方式,包裡面存放的是子產品
  • 用于将子產品包含在一起的檔案夾就是包
  • 自定義包的結構
|---包
    |---|---  __init__.py  包的标志檔案
    |---|---  子產品1
    |---|---  子產品2
    |---|---  子包(子檔案夾)
    |---|---|---  __init__.py
    |---|---|---  子包子產品1
    |---|---|---  子包子產品2
               
  • 包的導入操作
    • import package_name
      • 直接導入一個包,可以使用__init__.py中的内容
      • 使用方式是:

        package_name.func_name

        package_name.class_name.func_name()

      • 此種方式的通路内容是
      • 案例 pkg01, p07.py
    # pkg01.__init__py
        def inInit():
            print("I am in init of package")
    
        # pkg01.p01.py
        class Student():
            def __init__(self, name = "NoName", age = 18):
                self.name = name
                self.age = age
        
            def say(self):
                    print("My name is {0}".format(self.name))
        
            def sayHello():
                print("Hi, ")
    
    
        print("我是子產品p01")           
    # 案例 p07.py
        import pkg01
        
        pkg01.inInit()           
    I am in init of package
               
    • import package_name as p
      • 具體用法跟作用方式,跟上述簡單導入一緻
      • 注意的是此種方法是預設對__init__.py内容的導入
    • import package.module
      • 導入包中某一個具體的子產品
      • 使用方法
        package.module.func_name
            package.module.class.fun()
            package.module.class.var           
      • 案例 p08.py
    # 案例 p08.py
        import pkg01.p01
        
        stu = pkg01.p01.Student()
        stu.say()           
    我是子產品p01
        My name is NoName
               
    • import package.module as pm
  • from ... import 導入
    • from package import module1, module2, module3, ... ...
    • 此種導入方法不執行

      __init__

      的内容
      from pkg01 import p01
      p01.sayHello()           
    • from package import *
      • 導入目前包

        __init__.py

        檔案中所有的函數和類
      • func_name()

        class_name.func_name()

        class_name.var

      • 案例 p09.py, 注意此種導入的具體内容
    # 案例 p09.py
        from pkg01 import *
        
        inInit()
        
        stu = Student()            
    I am in init of package
        
        NameError: name 'Student' is not defined           
  • from package.module import *
    • 導入包中指定的子產品的所有内容
  • 在開發環境中經常會引用其他子產品,可以在目前包中直接導入其他子產品中的内容
    • import 完整的包或者子產品的路徑
  • __all__

    的用法
    • 在使用from package import 的時候, 可以導入的内容
    • __init__.py

      中如果檔案為空,或者沒有

      __all__

      , 那麼隻可以把

      __init__

      中的内容導入
    • __init__

      如果設定了

      __all__

      的值,那麼則按照

      __all__

      指定的子包或者子產品進行加載
    如此則不會載入

    __init__

    中的内容
    • __all__=['module1', 'module2', 'package1'... ...]

    • 案例 pkg02,p10.py
    # pkg02.__init__.py
        __all__=['p01']
        
        def inInit():
            print("T am in init of package")
    
        # pkg02.p01.py
        class Student():
            def __init__(self, name = "NoName", age = 18):
                self.name = name
                self.age = age
    
            def say(self):
                print("My name is {0}".format(self.name))
        
            def sayHello():
                print("Hi, ")
        
        # 此判斷語句建議一直作為程式的入口
        if __name__ == '__main__':
            print("我是子產品p01")           
    # 案例 p10.py
        from pkg02 import *
        
        stu = p01.Student()
        stu.say()           
    My name is NoName           

命名空間

  • 用于區分不同位置不同功能但相同名稱的函數或者變量的一個特定字首
  • 作用是防止命名沖突

    setName()

    Student.setName()

    Dog.setName()