python组织结构:包、模块(文件)、类(函数和变量)。
在Python中模块概念和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块
文件夹中必须包含__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__
使用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__
的值取决于你如何应用模块。如果 import 一个模块,
那么模块__name__
的值通常为模块文件名,不带路径或者文件扩展名。但是你也可以像一个标准的程序样直接运行模块,
在这 种情况下__name__
的值将是一个特别缺省"__main__"
。
一般使用__name__
来保证python程序只有一个入口:
if(__name__ == "__main__"):
print("程序入口")
# 程序入口
构建并发布一个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
安装的方式:
- 找到模块的压缩包
- 解压
- 进入文件夹
- 执行命令
python setup.py install
,或可以指定路径python setup.py install --prefix=安装路径
模块的引入:
- 在程序中,使用from import 即可完成对安装的模块使用
import sys
#通过sys模块的argv可以获取程序启动时的入参
print(sys.argv)
模块的path属性存储了模块导入时的搜索路径
import sys
path = sys.path
# 添加导入模块的搜索路径,这样就可以导入对应路径下的模块了
sys.path.append("xxx")
一个模块只能被导入一次,当导入一个模块后,即使再次使用import也不会重新导入,如果模块被导入后发生了改变,那么无法使用到被导入模块新的功能,此时只能使用reload函数:
import x
from imp import *
reload(x)
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关键字
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任何模块的情况下,就能使用这么多丰富的函数和功能了。
- 包和模块不会被重复导入
- 避免循环导入
- 程序设计上分层,降低耦合
- 导入语句放在后面需要导入时再导入,例如放在函数体内导入
- 保证只有一个入口文件,每个模块被导入时其中的代码会被执行一次