PYTHON 之 模块和包

1. 模块

  • 一个模块就是一个包含python代码的文件, 后缀名成是.py就可以,模块就是个python文件
  • 为什么我们用模块
    • 程序太大,编写维护非常不方便,需要拆分
    • 模块可以增加代码重复利用的方式
    • 当做命名空间使用,避免命名冲突
  • 如何定义模块
    • 模块就是一个普通文件,所以任何代码可以直接书写,
    • 不过根据模块的规范,最好在木块中编写以下内容
      • 函数(单一功能)
      • 类(相似功能的组合,或者类似业务模块)
      • 测试代码
# 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, 欢迎来到图灵学院!")

print("我是模块p01呀,你特么的叫我干毛")
  • 如何使用模块
    • 模块直接导入
# p02.py
import p01

stu = p01.Student("xiaojign", 19)

stu.say()

p01.sayHello()
  • 假如模块名称直接以数字开头,需要借助importlib帮助

  • 语法

    import module_name
    module_name.function_name
    module_name.class_name

  • 案例 01, 02,p01,p02



# 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("我是模块p01呀,你特么的叫我干毛")

#02.py
# 借助于importlib包可以实现导入以数字开头的模块名称
import importlib

# 相当于导入了一个叫01的模块并把导入模块赋值给了tuling
tuling = importlib.import_module("01")


stu = tuling.Student()
stu.say()
  • import 模块 as 别名
    - 导入的同时给模块起一个别名
    - 其余用法跟第一种相同
    - 案例 p03
import p01 as p

stu = p.Student("yueyue", 18)
stu.say()

- from module_name import func_name, class_name
    - 按上述方法有选择性的导入
    - 使用的时候可以直接使用导入的内容,不需要前缀
    - 案例 p04
from p01 import Student, sayHello


stu = Student()

stu.say()


sayHello()
  • from module_name import *
    • 导入模块所有内容
    • 案例 p05
from p01 import *


sayHello()

stu = Student("yaona", 28)
stu.say()
  • if __name__ == "__main__ 的使用
    • 可以有效避免模块代码被导入的时候被动执行的问题
    • 建议所欲程序的入口都以此代码为入口
    • 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呀,你特么的叫我干毛")

2. 模块的搜索路径和存储

  • 什么是模块的搜索路径:
    • 加载模块的时候,系统会在那些地方寻找此模块
  • 系统默认的模块搜索路径
    import sys
    sys.path 属性可以获取路径列表
    # 案例 p06.py
import sys

print( type(sys.path ))
print( sys.path )

for p in sys.path:
    print(p)

PYTHON 之 模块和包

  • 添加搜索路径

       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
        PYTHON 之 模块和包

#__init__.py
def inInit():
    print("I am in init of package")
# 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, 欢迎来到图灵学院!")



print("我是模块p01呀,你特么的叫我干毛")

p07.py 调用pkg01: 注意的是此种方法是默认对__init__.py内容的导入

import pkg01

pkg01.inInit()


  • import package_name as p
    - 具体用法跟作用方式,跟上述简单导入一致
    - 注意的是此种方法是默认对__init__.py内容的导入

    • import package.module
      • 导入包中某一个具体的模块,

      • 使用方法

          package.module.func_name
          package.module.class.fun()
          package.module.class.var
        
      • 案例 p08.py

import pkg01.p01


stu = pkg01.p01.Student()
stu.say()
  • 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, 注意此种导入的具体内容

from pkg01 import *


inInit()


stu = Student() #执行有问题!!!
  • from package.module import *

    • 导入包中指定的模块的所有内容

    • 使用方法

        func_name()
        class_name.func_name()  
      
  • 在开发环境中经常会所以用其他模块,可以在当前包中直接导入其他模块中的内容

    • import 完整的包或者模块的路径
  • __all__ 的用法

    • 在使用from package import * 的时候, * 可以导入的内容
    • __init__.py中如果文件为空, 或者没有 __all__, 那么只可以把__init__中的内容导入
    • __init__ 如果设置了__all__的值,那么则按照__all__ 指定的子包或者模块进行加载
      如此则不会载入__init__中的内容
    • __all__=['module1', 'module2', 'package1'.........]

    PYTHON 之 模块和包

  • pkg02
    init.py


__all__=['p01']

def inInit():
    print("I am in inti of pacakge")

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调用包pkg02
from pkg02 import *

stu = p01.Student()
stu.say()


inInit()# 注意:此时该语句报错!!!!因为只执行了__all__['p01']的内容!!!

命名空间

  • 用于区分不同位置不同功能但相同名称的函数或者变量的一个特定前缀

  • 作用是防止命名冲突

      setName()
      Student.setName()
      Dog.setName()