Skip to content

Latest commit

 

History

History
226 lines (170 loc) · 6.85 KB

06-包与模块.md

File metadata and controls

226 lines (170 loc) · 6.85 KB

python组织结构

python组织结构:包、模块(文件)、类(函数和变量)。

在Python中模块概念和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块


1 包

文件夹中必须包含__init__.py才被认为是一个包,__init__.py本身也是一个模块,它的名字是包的名字。

当一个包被导入时,__init__.py会被自动运行。__init__.py的应用场景:

  • __init__.py做一些包的初始化工作
  • 指定使用*导入时,哪些模块可以被导入,使用__all__ = ['模块名']控制
  • __init__.py没有内容时,
  • 导入公共模块,比如p包中的init导入了sys模块,则导入p包的模块可以以p.sys.变量名形式使用sys中的变量
  • 内置变量__name__变量的结果能够判断出,是直接执行的python脚本还是被引入执行的,如果是直接执行python脚本,则__name____main__

2 导入

使用import导包,import只能导入模块。使用as操作可以对导入的模块重命名:

import datetime
import string as s

导入模块的一部分,使用from 模块 import 变量1, 变量2, 变量3

from datetime import  date

使用*可以导入模块所有内容

from string import *

控制*导入的模块内容

__all__ = ['a'] # 此时使用*导入该模块,只导入变量a
a = 3
b =4

当你导入一个模块,Python解析器对模块位置的搜索顺序是: - 当前- 目录 - 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。 - 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/ - 模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

__name__属性

__name__属性: 模块是对象,并且所有的模块都有一个内置属性__name__。一个模块的 __name__ 的值取决于你如何应用模块。如果 import 一个模块, 那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。但是你也可以像一个标准的程序样直接运行模块, 在这 种情况下__name__ 的值将是一个特别缺省"__main__"

一般使用__name__来保证python程序只有一个入口:

if(__name__ == "__main__"):
    print("程序入口")
    # 程序入口

3 发布包

构建并发布一个Python包:

项目结构

├── setup.py
├── suba
│   ├── aa.py
│   ├── bb.py
│   └── __init__.py
└── subb
    ├── cc.py
    ├── dd.py
    └── __init__.py

构建脚本

编辑setup.py文件,py_modules需指明所需包含的py文件:

from distutils.core import setup

setup(name="author", version="1.0", description="author's module", author="author", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])

构建模块

执行python setup.py build,构建后目录结构:

├── build
│   └── lib.linux-i686-2.7
│       ├── suba
│       │   ├── aa.py
│       │   ├── bb.py
│       │   └── __init__.py
│       └── subb
│           ├── cc.py
│           ├── dd.py
│           └── __init__.py
├── setup.py
├── suba
│   ├── aa.py
│   ├── bb.py
│   └── __init__.py
└── subb
    ├── cc.py
    ├── dd.py
    └── __init__.py

生成发布压缩包

执行python setup.py sdist


4 模块安装、使用

安装的方式:

  • 找到模块的压缩包
  • 解压
  • 进入文件夹
  • 执行命令python setup.py install,或可以指定路径python setup.py install --prefix=安装路径

模块的引入:

  • 在程序中,使用from import 即可完成对安装的模块使用

5 给程序传参

import sys
#通过sys模块的argv可以获取程序启动时的入参   
print(sys.argv)

6 模块的导入路径

模块的path属性存储了模块导入时的搜索路径

import sys
path = sys.path
# 添加导入模块的搜索路径,这样就可以导入对应路径下的模块了
sys.path.append("xxx") 

7 重新导入

一个模块只能被导入一次,当导入一个模块后,即使再次使用import也不会重新导入,如果模块被导入后发生了改变,那么无法使用到被导入模块新的功能,此时只能使用reload函数:

import x
from imp import *
reload(x)

8 变量作用域

Python的作用域一共有4种,分别是:

  • L (Local):当前所在命名空间(如函数、模块),函数的参数也属于命名空间内的变量
  • E (Enclosing):外部嵌套函数的命名空间(闭包中常见)
  • G (Global):全局变量,函数定义所在模块的命名空间
  • B (Built-in) :内建模块的命名空间

Python 中只有模块(module),类(class)以及函数(def、lambda)中才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的, 也就是说这些语句内定义的变量,外部也可以访问,定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

Python 使用 LEGB 的顺序来查找一个符号对应的对象,即locals -> enclosing function -> globals -> builtins

global 和 nonlocal关键字

当内部作用域想修改外部作用域的变量时,需要用到global和nonlocal关键字

g_num = 1
def fun1():
    global g_num  # 需要使用 global 关键字声明
    print(g_num) 
    num = 123
    print(num)
    
# 如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字
def outer():
    l_num = 10
    def inner():
        nonlocal l_num   # nonlocal关键字声明
        l_num = 100
        print(l_num)
    inner()
    print(l_num)

def test_global_local():
    print(globals())  # 返回可以访问的所有全局变量
    print(locals())  # 返回所有可以访问的本地变量    

内建模块的命名空间

Python 在启动的时候会自动为我们载入很多内建的函数、类,比如 dict、list、type、print这些都位于__builtin__模块中, 可以使用 dir(__builtin__) 来查看。 这也是为什么我们在没有 import任何模块的情况下,就能使用这么多丰富的函数和功能了。


10 注意

  • 包和模块不会被重复导入
  • 避免循环导入
    • 程序设计上分层,降低耦合
    • 导入语句放在后面需要导入时再导入,例如放在函数体内导入
  • 保证只有一个入口文件,每个模块被导入时其中的代码会被执行一次