python学习笔记013——模块

时间:2024-05-13 13:34:14

1 模块module

1.1 模块是什么

模块是包含一系列的变量,函数,类等程序组

模块通常是一个文件,以.py结尾

1.2 模块的作用

1. 让一些相关的函数,变量,类等有逻辑的组织在一起,使逻辑更加清晰,

2. 模块中的变量,函数和类等可提供给其他模块或程序使用

1.3 模块的分类

1.内置模块(builtins),在解释器的内部,可以直接使用

2.标准库模块,随python的解释器一起安装,可直接使用(有的是用C语言写的,有的是用python写的)

3.第三方模块(通常为开源),需要自己安装

4.用户自定义模块

1.4 模块化编程的优点

1.有利于多人合作开发

2.使代码更加易于维护

3.提高代码的重用率

4.模块话编程有助于解决函数名和变量名冲突问题

1.5 模块的文档字符串

模块内的第一行未赋值给任何变量的字符串为模块的文档字符串,可用help(模块名)来查看

例如在test1.py模块中

'''
这是test.py模块文件

这个模块是学习测试时使用
这个模块*有 个变量,其中函数变量有 个
'''

def fun1(a,b):
    a = 1
    b = 2
    pass

def fun2(m,n):
    pass

para1 = "a"
para2 = "b"

c = map(fun1,[1,2])

print("test1模块被调用了")

经过如下操作

>>> import test1
test1模块被调用了
>>> help(test1)

可以得到下面的帮助页面

Help on module test1:

NAME
    test1 - 这是test.py模块文件

DESCRIPTION
    这个模块是学习测试时使用
    这个模块*有 个变量,其中函数变量有 个

FUNCTIONS
    fun1(a, b)

    fun2(m, n)

DATA
    c = <map object>
    para1 = 'a'
    para2 = 'b'

FILE
    /home/tarena/桌面/day13/test1.py

~
(END)

当函数中也有文档字符串时,则放在第一章节说明

2 模块的导入

借助于 import语句

  1. import XXX
  2. from XXX import YYY
  3. from XXX import *  # * 表示通配符

2.1 improt 语句

作用

将模块整体导入到当前的模块作用域(导入之后,通过dir(),可以直接显示该模块名)

语法

import 模块名1 [as 模块新名1] [,模块名2[as 模块新名2]]....

示例

导入数学模块

import math   #导入数学模块

交互模式下导入数学模式

>>> import math

导入前

>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

导入后

>>> import math
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math']
>>> import os
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math', 'os']

dir(obj) 返回所有属性的字符串列表

>>> dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']

help(obj) 查看模块的文档字符串

>>> import math
>>> help(math)

会显示模块的文档字符串

Help on built-in module math:
NAME
    math
DESCRIPTION
    This module is always available.  It provides access to the
    mathematical functions defined by the C standard.
FUNCTIONS
    acos(...)
        acos(x)
        Return the arc cosine (measured in radians) of x.
    .......  #此处省略部分函数名称
    tanh(...)
        tanh(x)
        Return the hyperbolic tangent of x.
DATA
    e = 2.718281828459045
    inf = inf
    nan = nan
    pi = 3.141592653589793

FILE
    (built-in)
(END)

用法:模块名.属性名

示例1 :打印常量π

>>> import math
>>> print(math.pi)
3.141592653589793

注意:必须是小写,没有大写 PI 变量

示例2 :求5的阶乘

>>> import math
>>> print(math.factorial(5))
120

2.2 from improt 语句

作用

将某模块的一个或多个属性导入到当前模块的作用域

语法

from 模块名 import 模块属性名1 [as 属性新名1] [,模块名属性2 [as 属性新名2]]

示例

from math import sin
from math import sin, sin, cos
from math import pi     #将math.pi导入到当前
from math import factorial as f    #将factorial 缩写为 f
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> from math import sin
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'sin']

在这里,就可以直接使用 sin 函数

2.3 from import * 语句

作用

将某模块的所有属性导入到当前模块

语法

from 模块名 import *

示例

>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> from math import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
>>> sin(pi/2)
1.0
>>> factorial(5)
120

缺点
可能会引入模块中的变量与自定义变量冲突.一般将其写在模块的头部,尽量避免导入模块中的变量将自定义变量值改变

2.4 模块加载初步介绍

无论是上述三种( improt 语句 、 from improt 语句 、 from import * 语句 )的那种形式,首次加载时将模块中的变量全部加载。

在模块导入时,无论那种导入方式,模块的所有语句会被执行

如果一个模块已经导入,则再次导入时不会重新执行模块内的语句

如test1.py模块

'''
这是test.py模块文件

这个模块是学习测试时使用
这个模块*有 个变量,其中函数变量有 个
'''

def fun1(a,b):
    a = 1
    b = 2
    pass

def fun2(m,n):
    pass

para1 = "a"
para2 = "b"

c = map(fun1,[1,2])

print("test1模块被调用了")

在交互模式下运行

>>> import test1
test1模块被调用了
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'test1']
>>> dir(test1)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'c', 'fun1', 'fun2', 'para1', 'para2']

注意:尽管 print() 函数加载了,但是使用 dir() 返回参数列表时,函数变量 print() 和 map() 并没有出现在该模块范围内

为了更明显地显示首次加载模块时是将模块中的“全局”变量均加载一遍,现重新在交互模式下运行

>>> from test1 import fun1
test1模块被调用了
>>> from test1 import para1
>>> dir(test1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'test1' is not defined
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'fun1', 'para1']

我们可以看到首次调用时有“test1模块被调用了”,但是第二次调用test1模块中的para1时,就没有出现“test1模块被调用了”。

同时我们可以看到查看test1模块的变量时,显示test1没有定义,也即test1没有被引用到当前模块中

dir()时,可以显示当前模块的全部变量,则有test1模块中的fun1para1两个变量调用到当前模块

注意这里面的关系。

模块中的函数也有文档字符串时

'''
这是test.py模块文件

这个模块是学习测试时使用
这个模块*有 个变量,其中函数变量有 个
'''

def fun1(a,b):
    '''
    这个是fun1测试函数

    函数中有两个变量
    :param a:
    :param b:
    :return:
    '''
    a = 1
    b = 2
    pass

在交互模式下运行

>>> import test1
>>> help(test1)

则有

Help on module test1:

NAME
    test1 - 这是test.py模块文件

DESCRIPTION
    这个模块是学习测试时使用
    这个模块*有 个变量,其中函数变量有 个

FUNCTIONS
    fun1(a, b)
        这个是fun1测试函数

        函数中有两个变量
        :param a:
        :param b:
        :return:

FILE
    /home/tarena/桌面/day13/test1.py

在上述案例中同时交互模式下运行

>>>help(test1.fun1)

则有

Help on function fun1 in module test1:

fun1(a, b)
    这个是fun1测试函数

    函数中有两个变量
    :param a:
    :param b:
    :return:
(END)

3 常见的模块(内置&标准库模块)

内置模块有:builtins  sys  time  posix  itertools等
标准库模块:random  math  datetime  os  xml  re  functools等

3.1 数学模块 math

在 linux 是内建模块,在 os 中是标准库模块
math.e 自然对数的底
math.pi π

math.sin(x)
math.cos(x)
math.tan(x)
math.asin(x)
math.acos(x)
math.atan(x)
math.degrees(x)# 弧度转角度
math.radians(x)#角度转弧度
math.ceil(x) 向上取整
math.floor(x) 向下取整
math.sqrt(x)  求平方根
math.factorial(x) x的阶乘
math.log(x[,base])
math.log10(x)
math.pow(x,y)
math.fabs(x)

三角函数中的x是以弧度为单位的

4 模块的属性

4.1 __name__属性:

作用:

1 记录模块名

2 用来判断是否为主模块

说明:

1 对于被导入模块,模块名 = 文件名 - "路径 前缀" 和 .py后缀

2 对于主模块,模块名为"__main__"

示例:

模块test1

def mysum(begin: "开始", end: "结束(不包含end)")-> int:
    s = 0
    for x in range(begin, end):
        s += x
    return s

def mymax(a, b, c):
    m = a
    if b > m:
        m = b
    if c > m:
        m = c
    return m

name1 = "audi"
name2 = "tesla"

print("test1 模块被加载!")
print("test1 模块内的__name__属性的值为:",__name__)

模块test2

import test1  # 导入定义的模块

print("5+6+7+...+ 100的和是:",
      test1.mysum(5, 101))

print("最大的一个数是:", test1.mymax(1,2,3))
print("test1.name1=", test1.name1)
print("test2 模块内的__name__属性的值为:",__name__)

运行test2模块

test1 模块被加载!
test1 模块内的__name__属性的值为: test1
5+6+7+...+ 100的和是: 5040
最大的一个数是: 3
test1.name1= audi
test2 模块内的__name__属性的值为: __main__

4.2 __doc__属性

用来记录文档字符串, mymod.__doc__

4.3 __file__属性

用来记录模块的文件路径

注意:内建模块没有 __file__ 属性,自定义的模块存在这个属性值

内建模块:

>>> import math
>>> math.__file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'math' has no attribute '__file__'

自定义模块

>>> import test1  #导入4.1中的test1模块
test1 模块被加载!
test1 模块内的__name__属性的值为: test1
>>> test1.__file__
'/home/tarena/桌面/day13/test1.py'

4.3 __all__属性

用来存放可导出属性的列表,此列表中的元素是字符串

当以 from  模块 import * 这样形式从模块中将变量导入另外一个模块时,在模块开始处加入 __all__ 时,

只有该属性内的值才能被带入。

这样可以避免该模块下的所有变量导入到另外一个模块,过滤掉不想被调用的参数

模块test3

__all__ = ['hello1', 'name1']

def hello1():
    pass

def hello2():
    pass

name1 = "模块"
name2 = "加载"

print("test3 模块被加载!")

交互模式下运行test3模块

>>> from test3 import *
test3 模块被加载!
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'hello1', 'name1']

但是当是 import 模块 或 from 模块 import 函数名 时是无效的。

>>> import test3
test3 模块被加载!
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'test3']
>>> dir(test3)
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'hello1', 'hello2', 'name1', 'name2']

4.4 时间模块time

写时间相关的模块
UTC 先将a地时间转成UTC时间,再将UTC时间转为b地时间
时间元组(年,月,日,时,分,秒,星期几,元旦开始日,夏令时修正时间)
公元纪年  0000-1-1 0:0:0
计算机元年 1970-1-1 0:0:0

4.5 随机模块random

import random as R
R.random() 返回一个[0,1)之间的随机浮点数
R.uniform(a.b) 返回一个[a.b)之间的随机浮点数

4.6 模块中的隐藏属性

模块中'__'(双下划线)开头,不是以"__"结尾的属性,在 import 模块    或  from 模块 import *  导入时,将不被导入

Python高级特性:私有属性

5 模块的加载

5.1 模块的加载过程

1 先搜索相关路径找模块(.py文件)

2 判断是否有此模块对应的.pyc,如果.pyc文件是有最新的.py文件生成(其实就是比较两文件的最后时间),则直接加载.pyc(compile)

3 如果.pyc文件的生长时间比.py晚,说明.py文件已经修改但没有生成新的.pyc文件,则生成.pyc文件并将其加载执行

mymod.py --(编译)-> mymod.pyc --(解释执行)->python3

5.2 模块路径的搜索顺序

1 搜索当前路径

2 sys.path提供的路径

3 搜索内置模块

5.3 sys模块

sys.path 模块的搜索路径

sys.platform 操作系统平台信息

sys.argv 命令行参数

sys.exit() 推出程序

5.4 添加模块的加载路径

1 方法1

import sys
#sys.path.append("mymod.py所在的绝对路径")
sys.path.append("/home/tarena/waid1710/day13/code")
import mymod.py #成功

2 方案2

将路径添加在pythonpath环境变量中,该语法为linux与shell想结合的语法
例如:

#$ export PYTHONPATH = $PYTHONPATH:mymod.py的绝对路径
$ export PYTHONPATH=$PYTHONPATH:/home/tarena/waid1710/day13/code

加载后,通过sys.path 可以查看到该路径

PYTHONPATH环境变量
PYTHONPATH环境变量里的值或自动添加到sys.path列表中