Python 3 模块

Python 模块 (Module),是一个 Python 文件,以 .py 结尾,可以包含了 Python 类定义,函数定义和一些 Python 语句

也就是说,我们随便写一个 .py 结尾的文件就是在定义一个模块,比如之前写的 main.py

模块能定义函数,类和变量,模块里也能包含可执行的代码

模块最重要的作用,就是可以按照功能和逻辑划分我们的代码到不同的文件中

比如我们把 greeting() 函数放到 helpfunc.py 文件里就形成了 helpfunc 模块

helpfunc.py

def greeting( name ):
   print ("Hello : ", name)
   return

import 语句

模块定义好了以后,就可以使用 import 语句来引入模块了

语法

import module1[, module2[,... moduleN]

比如要引用模块 math,就可以在文件最开始的地方使用 import math 来引入

这时候要调用 math 模块中的函数,就必须这样使用

模块名.函数名

当 Python 解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入

搜索路径

搜索路径是一个解释器会先进行搜索的所有目录的列表

如想要导入模块 helpfunc.py,需要把命令放在脚本的顶端

main.py

#!/usr/bin/python

## 导入模块
import helpfunc

# 现在可以调用模块里包含的函数了
helpfunc.greeting("简单教程")

运行以上 Python 代码,输出结果如下

Hello : 简单编程

注意

在一个模块内,不管在任何地方,执行了多少次 import,模块也只会被导入一次

这样可以防止导入模块被一遍又一遍地执行

from...import 语句

Python 的 from...import 可以从模块中导入一个指定的部分到当前命名空间中

from modulename import name1[, name2[, ... nameN]]

例如,要导入 math 模块的 sqrt() 函数,可以这样

from math import sqrt

这个语句不会把整个 math 模块导入到当前的命名空间中,它只会将 math 里的 sqrt 函数引入到执行这个声明的模块的全局符号表

这时候要调用 sqrt() 函数,就可以这样使用了

#!/usr/bin/python

## 导入模块
from math import sqrt

# 现在可以调用模块里包含的函数了
sqrt(16)

from...import * 语句

我们也可以使用 from...import * 语句把一个模块的所有内容全都导入到当前的命名空间

from modname import *

这条语句提供了一个简单的方法来导入一个模块中的所有项目

注意: 这种语句是不被推荐的,因为会污染当前的模块

例如我们想一次性引入 math 模块中所有的东西,可以如下使用

from math import *

搜索路径

当 Python 遇到 import 语句需要导入一个模块时,会根据一定的规则搜索模块

  1. 当前目录

  2. 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录

  3. 如果都找不到,Python 会察看默认路径

    UNIX下,默认路径一般为 /usr/local/lib/python/

模块搜索路径存储在 sys 模块的 sys.path 变量中

显示当前的导入路径

import sys
print ( sys.path )

变量里包含当前目录,PYTHONPATH 和 安装过程中设定的默认目录

PYTHONPATH 变量

作为环境变量,PYTHONPATH 是一个由逗号分隔的许多目录组成

PYTHONPATH 的语法和 shell 变量 PATH 的一样

Windows 系统下,PYTHONPATH 一般如下

set PYTHONPATH=c:\python\lib;

UNIX 系统下,PYTHONPATH 一般如下

export PYTHONPATH=/usr/local/lib/python

命名空间和作用域

命名空间是一个包含了变量名称和它们对应的值组成的字典

一个 Python 表达式可以访问局部命名空间和全局命名空间里的变量

如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量

每个函数都有自己的命名空间,类的方法的作用域规则和通常函数的一样

Python 会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的

因此,如果要给函数内的全局变量赋值,必须使用 global 语句

global VarName 的表达式会告诉 Python, VarName 是一个全局变量,这样 Python 就不会在局部命名空间里寻找这个变量了

例如,我们在全局命名空间里定义一个变量 income。我们再在函数内给变量 income 赋值,然后 Python 会假定 income 是一个局部变量。然而,我们并没有在访问前声明一个局部变量 income,结果就是会出现一个 UnboundLocalError 的错误

取消 global 语句的注释就能解决这个问题

#!/usr/bin/python

income = 6000
def incr_income():
   # 想改正代码就取消以下注释
   # global income
   income = income + 3000

print ( income )
incr_income()
print(incr_income)

dir() 函数

dir() 函数返回一个模块里定义过的名字列表

返回的列表包含了在一个模块里定义的所有模块,变量和函数

#!/usr/bin/python

# 导入内置 math 模块
import math

content = dir(math)

print (content)

运行以上 Python 代码,输出结果如下

['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 
'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 
'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 
'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 
'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']

特殊字符串变量 __name__ 指向模块的名字,__file__ 指向该模块的导入文件名

import math

print (math.__name__)
print (math.__file__)

运行以上 Python 代码,输出结果如下

math
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/math.so

globals() 和 locals() 函数

globals()locals() 函数会返回全局和局部命名空间里的名字

  1. 如果在函数内部调用 locals() ,返回的是该函数里能够访问的名字(标识符)
  2. 如果在函数内部调用 globals() ,返回的是该函数里能访问的全局名字

两个函数的返回类型都是字典

所有所有的名字都可以使用 keys() 函数获取

#!/usr/bin/python

# 导入内置 math 模块

name = 'in main.py'
email = 'servers@twle.cn'

def your_name():
    print ('---函数内----')
    age = 28
    print (locals())
    print (globals())

print ('---调用函数前----')
print (locals())
print (globals())
your_name()
print ('---调用函数后-----')
print (locals())
print (globals())

运行以上 Python 代码,输出结果如下

$ python main.py 
---调用函数前----
{'name': 'in main.py', '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'main.py', '__package__': None, 'email': 'servers@twle.cn', 'your_name': <function your_name at 0x10d30bc08>, '__name__': '__main__', '__doc__': None}
{'name': 'in main.py', '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'main.py', '__package__': None, 'email': 'servers@twle.cn', 'your_name': <function your_name at 0x10d30bc08>, '__name__': '__main__', '__doc__': None}
---函数内----
{'age': 28}
{'name': 'in main.py', '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'main.py', '__package__': None, 'email': 'servers@twle.cn', 'your_name': <function your_name at 0x10d30bc08>, '__name__': '__main__', '__doc__': None}
---调用函数后-----
{'name': 'in main.py', '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'main.py', '__package__': None, 'email': 'servers@twle.cn', 'your_name': <function your_name at 0x10d30bc08>, '__name__': '__main__', '__doc__': None}
{'name': 'in main.py', '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'main.py', '__package__': None, 'email': 'servers@twle.cn', 'your_name': <function your_name at 0x10d30bc08>, '__name__': '__main__', '__doc__': None}

reload() 函数

使用 import 语句将一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次

如果想重新执行模块里顶层部分的代码,就要使用 reload() 函数

该函数会重新 加载 之前导入过的模块

reload(module_name)

参数 module_name 为要重新加载的模块的名字,而不是一个字符串形式,比如想重载 math 模块,可以如下使用

reload(hello)

Python 中的包

Python 是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境

简单来说,包就是文件夹,但该文件夹下必须存在 __init__.py 文件

__int__.py 用于标识当前文件夹是一个包, 该文件的内容可以为空

比如一个在 package_demo 目录下的 demo1.py、demo2.py、__init__.py 文件,test.py 为测试调用包的代码

目录结构如下

test.py
package_demo
|-- __init__.py
|-- demo1.py
|-- demo2.py

文件内容如下

package_demo/demo1.py

def demp1():
   print ("I'm in demo1")

package_demp/demo2.py

def demp2():
   print ("I'm in demo2")

然后在 package_demo 目录下创建 __init__.py

package_demo/__init__.py

if __name__ == '__main__':
    print ('作为主程序运行')
else:
    print ('package_demo 初始化')

最后在 package_demo 同级目录下创建 test.py 来调用 package_demo

test.py

#!/usr/bin/python

# 导入 Phone 包
from package_demo.demo1 import demo1
from package_demo.demo2 import demo2

demo1()
demo2()

运行以上所有的 Python 代码,输出结果如下

package_demo 初始化
I'm in demo1
I'm in demo2

上面的范例,虽然我们只在每个文件里定义一个函数,但其实可以放置许多函数

还可以在这些文件里定义 Python 类,然后为这些类建一个包

Python3 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.