Python基础(七)--模块和包

 

目录

 

                               Python基础(七)--模块和包

1 模块

1.1 什么是模块

1.2 模块的使用

1.3 模块的搜索路径

1.4 模块的缓存

2 包

2.1 什么是包

2.2 包的使用

3 常用模块

3.1 math

3.2 random

3.3 time

3.4 datetime

3.5 sys


                               Python基础(七)--模块和包

1 模块

1.1 什么是模块

模块是一个Python文件,该文件包含相关的定义与语句(类,函数,变量)。模块具有名称,名称与文件的名称一致。

使用模块的好处:

①通过划分若干个模块,将项目程序进行明确的划分,从而将复杂问题简单化,同时,也能够进行更加合理的分工,有利于协作式开发程序。

②模块提供独立的命名空间,可以解决命名上的冲突。不同的模块中,定义相同名称的变量,不会产生命名冲突

③模块可以实现良好的重用性,在多人间实现共享。

1.2 模块的使用

每个项目可以划分为多个模块。但模块与模块之间,不可能都是完全孤立的。一个模块很可能需要与其他的一个(或多个)模块进行交互,因此,当需要在一个模块中使用其他模块定义的名称(函数,类,变量等),则需要首先导入该模块,然后通过模块名.名称进行访问。

(1)导入模块

使用import对模块进行导入:import 模块

我们还可以一次导入多个模块:import 模块1,模块2……

当导入模块时,该模块内的语句就会得到执行,但只会执行一次,即重复导入模块不会多次执行。当模块作为脚本执行时(使用python命令在命令行执行),模块中的语句也会得到执行。按照惯例,模块导入语句写在模块的最上方。

当导入模块后,我们就可以使用模块中所定义的名称,格式为:模块名.名称

①访问模块:可以将其他模块中定义的名称(全局命名空间中的名称)直接导入到当前模块的命名空间,这样,我们就可以直接通过名称访问,而无需使用模块名限定。格式如下:from 模块 import 名称1,名称2……

注意:这种导入方式要稍加留意,因为如果当前模块中也存在同样名称的定义,就会造成名称的冲突,也就是名称会重新绑定后来的对象。

②模块冲突:假设不考虑名称的冲突,只考虑访问的便捷性,使用from import的方式确实是不错的选择。但是,如果我们要使用该模块中定义的很多名称,一个个的导入可能会有些繁琐,此时,我们可以使用批量导入:from 模块 import *

这样就会将模块中除了以_开头的所有名称导入到当前模块的命名空间。然而,这种方式会导入很多名称,容易造成命名冲突,尽可能少用。

注意:在Python中一切都是对象,模块也是一个对象 。使用import导入模块的时候,模块定义的语句就会执行

(2)模块别名

当导入模块(或模块中的名称)时,我们可以使用as为模块(或模块中的名称)指定别名。语法如下:

      import 模块名 as 模块别名

      from 模块名 import 名称 as 名称别名

这样,我们就可以通过别名来访问模块(或模块中的名称)。但是,一旦指定别名后,原模块名(或原模块中的名称)将不再可用。

别名的好处:①解决名称冲突,②使用简短的别名,减少输入量。

(3)隐藏模块数据

因为使用import *的语法会在当前命名空间增加很多名称,为了减少import *所造成的影响(名称冲突),我们可以有选择性的隐藏模块的数据,进而限制使用import *时,名称的导入。

隐藏模块数据可以采用两种方式:①将名称以下划线(_)开头。②定义__all__变量。

上面两种隐藏方式仅是限制使用import *语法导入的名称,并不是表示该名称无法在模块外访问。使用import其他方式导入,还是能够在模块外进行访问的。他们的顺序为,会首先检查__all__变量,如果存在,会将__all__中指定的名称导入到当前的命名空间。如果不存在,则会将除下划线(_)开头的名称导入到当前的命名空间。即__all__中即使指定以下划线(_)开头的名称,该名称依然可以成功导入到当前的命名空间中。

①将名称以下划线(_)开头:如果模块中定义的名称以_开头,则在使用import *语法时,这些名称不会导入到当前模块的命名空间中,即当前模块无法直接访问该名称。

②定义__all__变量:如果使用from 模块 import *的语法,则默认情况下会导入模块中除_开头的所有名称,这容易与当前模块的命名造成冲突。我们可以定义__all__变量来限制导出名称的数量。当在模块中定义__all__变量时,该变量的值为一个字符串列表,只有列表中指定的名称才会导入到当前命名空间。

# 为了减少命名冲突,可以限制from 模块名 import * 的导入模块
# 显示的方式有两种:1.名称前使用_   2.在模块内定义__all__关联一个str类型的列表(列表中指定所有能用*导入的名称)
# 它们的顺序为:先查看__all__名称,如果该名称存在,则导入列表中所有的元素指定的名称,如果不存在,则导入
# 该模块下所有未使用_开头的名称,这意味着如果__all__中指定了_开头的名称,一样可以导入
from lead import *
print(a,b,_c)
print(__name__)
print("lead模块执行了")
# 指定可以由from import * 导入的名称
__all__ = ["a","b","_c"]
a = "在lead模块中定义的变量"
def b():
    print("在lead模块中定义的函数")
_c = "不会被from import * 语法导入"
d = "不在__all__列表内"

print("lead模块的__name__名称:" + __name__)

(4)__name__

在编写模块时,我们可能需要对当前模块的功能进行测试。当我们在其他模块中导入当前模块时,测试内容就会得到执行,这并不是期望的。因此,我们不得不将其去掉或者注释。可是,以后还需要再写入新的测试代码来验证新增功能的正确性,如此反复,非常不方便。

解决方法是:我们可以通过__name__属性来获取模块的名称。模块会在两种情况下执行:①当模块由其他模块导入时;②当模块作为脚本,在命令行使用python 文件名.py执行时。两种执行方式,通过__name__获取的模块名称是不一致的。当模块由其他模块导入时,模块的名称就是文件的名称,而模块作为脚本执行时,模块的名称为__main__。因此,我们可以据此获取模块执行的方式。

# __name__名称
# 作为脚本运行的模块,__name__固定返回__name__
# 作为被其他模块导入而运行时,__name__返回的就是当前模块的名称
# 为了方便测试,我们可以将测试语句写在:if __name__ == "__name__"中
def is_even_number(number):
    return number % 2 == 0
# 如果当前模块是作为脚本而执行没说明在测试该模块的功能,测试语句得到执行
if __name__ == "__name__":
    print(is_even_number(5))
    print(is_even_number(6))

 

1.3 模块的搜索路径

当我们导入模块时,解释器会按照如下顺序搜索:

①内置与解释器中的模块,如sys,math等;

②作为脚本执行的模块所在路径;

③PYTHONPATH环境变量指定的路径,如果该环境没有设置则忽略;

④Python安装相关路径,这包含Python语言的内建模块(os, random模块),以及安装的第三方模块(beautifulsoup,numpy模块)所在的路径等。

可以通过sys模块的path属性获得路径信息。path的值(列表类型)就是由后三项按顺序组成的(后三项路径的并集)。解释器会在这些路径中寻找模块名.py文件。

解释器会按顺序进行查找,以先找到的为准。因此,如果在不同的路径中都存在满足条件的模块,会以先找到的为准。

1.4 模块的缓存

导入模块时,Python会缓存所加载模块编译后的版本。从实现的角度,就是将导入模块的文件(*.py)编程成字节码文件(*.pyc)。这样在下次运行时,就会检查字节码所对应的源文件在编译过后是否经过修改,即字节码文件是否是对应源文件的最新版本。如果不是最新版本,则会对源文件重新进行编译。如果已经是最新版本,则会从字节码文件中读取信息,这样可以加快模块的加载速度。

编译的字节码(*.pyc)文件是平台无关的,即不管在什么平台,只要Python源文件的内容相同,编译过后的字节码文件也相同。字节码文件会保存在与作为脚本运行文件相同路径下的__pycache__目录中。格式为“模块名.解释器-版本.pyc”,例如,假设导入的模块为test,解释器为CPython3.6,则字节码文件名为“test.cpython-36.pyc”。

注意:①缓存字节码文件只是可以提供模块加载的速度,并不会提高模块运行的速度。

②只有导入的模块才会生成字节码文件,作为脚本运行的文件不会生成字节码文件。

③字节码文件可以脱离源文件而运行。

2 包

2.1 什么是包

包类似于操作系统中的文件夹(目录,路径)

包的作用:①提供对模块的分类管理

②提供独立的命名空间,可以解决模块的命名冲突

2.2 包的使用

(1)导入包

目录与子目录,目录与文件之间,使用特定的分隔符进行分隔。例如,Windows操作系统使用“\”,Linux系统使用“/”。同样,包也可以含有子包,包与包,包与模块之间使用“.”来分隔。可以通过import来导入包,或者是导入包中的模块。与之前导入模块的语法是相同的,例如:

import 包名

import 包名.模块名

from 包名 import 模块名

from 包名.模块名 import 名称

上面导入包的方式,我们称为绝对导入,此外,我们也可以进行相对导入。我们使用“.”来表示当前模块所在的包,使用“..”来表示当前模块所在包的父包(上级包)。例如:

from . import 名称

(2)__init__.py

在每一个包中,应该同时配有一个__init__.py文件(模块)。它的作用如下:

①该文件用来标记,当前的路径是一个包,而不是普通的目录,以避免目录名与模块名造成混淆

②该文件为包的初始化模块,当导入包,或者导入包的子包(子模块)时,该模块会自动执行。因此,我们可以在__init__.py中编写一些包的初始化语句;

③在__init__.py中定义的,具有全局作用域的名称,可以使用包名.名称进行访问(这些名称就会成为包(对象)的属性)

(3)__all__

我们可以在__init__.py中定义__all__变量,来控制导入哪些名称,这与模块中的定义的__all__变量意义相同,也是一个字符串的列表类型,指定能够导入的名称。

 

3 常用模块

3.1 math

math模块提供了与数学计算相关的功能。常用的功能如下:

名称 描述
pi 返回圆周率的值
e 返回数学常数

ceil(x)

返回大于等于x的最小整数(向上取整)
floor(x) 返回小于等于x的最大整数(向下取整)
exp(x) 返回e的x次幂,相当于math.e**x
pow(x,y) 返回x的y次幂,相当于x**y
log(x[,base]) 返回基于base为底,x的对数。base默认为e
fabs(x) 返回x(视为float类型)的绝对值
factorial(x) 返回x的阶乘,x需要是int类型,或者是小数点为0的浮点类型,并且不能为负。
fmod(x,y) 返回x与y取余的结果。注意:x % y是取模,二者结果可能是不同的。
fsum(itreable) 返回可迭代对象中每个值累计求和后的结果。
gcd(x,y) 返回x与y的最大公约数。x与y需要是整数类型
sqrt(x) 返回x的平方根

3.2 random

random模块提供生成随机数的功能(伪随机数)。常用功能如下:

名称 描述
random() 返回一个0~1之间的浮点数,包括0不包括1
randint(a,b) 返回一个a~b之间的整数,包括a与b

randrange(stop)/

randrange(start,stop[.step])

参数与range函数的意义相同,相当于从相同参数的range函数可能产生的值中,随便选择一个
uniform(a,b) 返回a与b之间的浮点数,包括端点
choice(seq) 从seq(可迭代对象)中随机选择一个元素,如果序列为空,则产生错误
choices(population, weights=None, *, cum_weights=None, k=1) 从population(可迭代对象)中选择k个元素,放入一个列表并返回。如果提供了weights(权重)或cum_weights(累积权重),则元素的选择概率会根据权重(累积权重)决定。权重与累积权重不能同时指定,因为权重内部会转换成累积权重,这样会造成不一致。如果没有指定权重与累积权重,则各个元素的选择概率相同。
sample(population, k) 从population(可迭代对象)中选择k个不同的元素,返回元素组成的列表。
shuffle(x[, random]) 对x(序列)进行洗牌(随机分配每个元素的位置)。random是一个可选的生成随机数的函数,函数的返回值为[0, 1),默认使用random模块的random函数。

3.3 time

time模块提供关于时间的操作

名称 描述
timezone 返回与UTC时间(世界标准时间)相差的秒数。正数表示晚于UTC时间,负数表示早于UTC时间。
time() 返回从新纪元(1970-01-01 00:00:00)到当前时间走过的秒数。
localtime([seconds]) 返回从新纪元走过seconds(秒数)后的时间。返回类型为time.struct_time类型(tuple的子类),如果seconds没有指定,则默认表示当前时间。该时间显示的是本地时间,要考虑对应的时区。例如,北京时间为东八区,比UTC时间早8小时,因此,需要在最后转换的时间上加上8小时。struct_time是一个命名元组(可以通过属性名访问,也可以通过索引访问)
gmtime([seconds]) 与localtime([seconds])的用法相同,只是返回的是UTC时间,而不是本地时间。
mktime(tuple) 将tuple(本地时间的元组)转换为从新纪元到元组指定时间走过的秒数。与localtime([seconds])函数正好是相反的
asctime([tuple]) 将tuple(时间元组)转换成字符串(str)的表示形式。如果没有提供tuple参数,则使用localtime()函数返回的元组(当前的本地时间)。
ctime([tuple]) 将从新纪元走过的毫秒数转换为本地时间。该函数相当于这样调用:asctime(localtime(seconds))。如果seconds参数没有指定,则使用time()函数返回的秒数。
sleep(seconds) 使当前程序暂停执行参数指定的时间。seconds可以是小数。
clock() 在Unix / Linux系统,该函数返回CPU的计算时间。在Windows操作系统,该函数第一次调用,返回CPU的计算时间,从第二次调用开始,返回距离第一次调用该函数所经历的时间。CPU的计算时间不包括调用sleep暂停的时间,因为在暂停时,CPU没有工作。因为该函数在不同操作系统上行为的不一致性,从Python3.3起,已经不建议使用,取而代之的是使用perf_counter()函数或者是 process_time()函数。
perf_counter() 返回精准的性能计数器,可以用来测试短时间的时间差。该时间包含调用sleep函数暂停的时间。该函数返回值所基于的时间点是不确定的,我们不能当成系统时钟来使用,但是可以多次调用该函数,计算一段程序执行的时间差。
process_time() 返回当前进程下,系统以及用户的CPU计算时间。该时间不包含调用sleep函数暂停的时间。
strftime(format[, tuple]) -> string 将tuple(时间元组)转换成format参数指定的格式的字符串。如果tuple没有指定,则使用localtime()函数返回的元组。format中可以含有特殊占位符,将使用元组中特定值进行替换,非特殊占位符会原样显示。
strptime(string, format) -> struct_time 按照format指定的格式,将string(时间格式字符串)解析为时间的元组。format的格式与strftime函数的format格式相同

struct_time类的格式

索引

属性名

说明

0

tm_year

年(四位数表示)。

1

tm_mon

月份(1 ~ 12)。

2

tm_mday

日(1 ~ 31)。

3

tm_hour

小时(0 ~ 23)。

4

tm_min

分(0 ~ 59)。

5

tm_sec

秒(0 ~ 61),60用来表示闰秒(跳秒),是对世界时间的一种调整。61因为历史原因所保留。

6

tm_wday

星期(0 ~ 6),周一为0,周日为6。

7

tm_yday

年度的第几天(1 ~ 366)。

8

tm_isdst

是否支持DST(daylight saving time),即夏令时(日光节约时间)。部分国家在天亮早的夏季,将时钟向前调整一小时,从而可以节约照明资源。可能值为0(不生效)、1(生效)或-1(未知)。

占位符

占位符

说明

%Y

年份(四位数字)。

%y

年份(两位数字)。

%m

月份(01 ~ 12)。

%d

日(01 ~ 31)。

%H

24小时制(00 ~ 23)

%I

12小时制(00 ~ 12)

%M

分钟(00 ~ 59)。

%S

秒(00 ~ 61)。

%w

周期几(0 ~ 6),周日为0。注意,与tm_wday的表示不一致。

%j

年度的第几天(001 ~ 366)。

%W

年度的第几周(00 ~ 53),星期一视为一周的第一天。在年度第一个周一之前的天视为第0周。

%U

年度的第几周(00 ~ 53),星期日视为一周的第一天。在年度第一个周日之前的天视为第0周。

%z

当前时区与UTC的时间差。格式为+HHMM(当前时区早于UTC)或-HHMM(当前时区晚于UTC)。

%Z

时区名称。

%a

本地星期的简写名。

%A

本地星期的全名。

%b

本地月份的简写名。

%B

本地月份的全名。

%c

本地日期与时间的恰当表示。

%x

本地日期的恰当表示。

%X

本地时间的恰当表示。

%p

显示AM或PM(或其本地等效的其他表示方式)。

%%

%的转义。

3.4 datetime

datetime模块提供date,time,datetime,timedelta等类,供我们对日期与时间进行操作。与time模块相比,datetime模块还额外增加了日期的加减与比较运算。

(1)date类

date类提供针对日期(不含时间)的操作。

构造器 date(year, month, day):用来创建参数指定日期的date对象。year指定年,month指定月,day指定日。
实例属性 year / month / day:返回年 / 月 / 日
类属性

max / min:最早的 / 最晚的date对象;

resolution:类属性两个不同date对象的最小差距值

实例方法 ctime():返回特定格式的字符串来表示日期;

replace(year=self.year, month=self.month, day=self.day):返回新的date对象,值为使用当前参数替换之后的结果。year指定要替换的年,month指定要替换的月,day指定要替换的日;

timetuple ():返回time.struct_time对象,类似于time.localtime()返回的结果;

weekday():返回当前日期是星期几(0 ~ 6)。星期一返回0,星期日返回6。

toordinal():返回当前日期的序数。1年1月1日序数为1,1年1月2日序数为2,以此类推;

strftime(format):根据format指定的格式,显示当前的日期对象。

类方法 today():类方法,返回当前的日期。

fromtimestamp(timestamp):从参数指定的timestamp(时间戳,即从新纪元走过的秒数)中创建date对象。

fromordinal(ordinal):根据参数指定的ordinal(序数)创建date对象。

(2)time类

time类提供针对时间的操作

构造器

time(hour=0, minute=0, second=0, microsecond=0):创建参数指定的time对象。hour指定小时,minute指定分钟,second指定秒,micorsecond指定微秒。

实例属性

hour / minute / second / microsecond:返回小时 / 分钟 / 秒 / 微秒

类属性

max / min:最早的 / 最晚的time对象;

resolution:类属性两个不同time对象的最小差距值

实例方法

replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond):创建一个新的time对象,值为参数指定的值替换之后的结果。hour指定要替换的小时,minute指定要替换的分钟,second指定要替换的秒,microsecond指定要替换的微秒。

strftime(format):根据format指定的格式,显示当前的时间对象。

(3)datetime类

datetime类提供针对日期与时间的操作,相当于是date与time两个类功能的并集。

构造器

datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0):用来创建参数指定日期的datetime对象。year,month与day三个参数是必须的。

实例属性

year / month / day:返回年 / 月 / 日

hour / minute / second / microsecond:返回小时 / 分钟 / 秒 / 微秒。

类属性

max / min:最早的 / 最晚的datetime对象;

resolution:类属性两个不同datetime对象的最小差距值

实例方法

date():返回date对象,年,月,日与datetime对象的年,月,日相同。

time():返回time对象,时,分,秒,微秒与datetime对象的时,分,秒,微秒相同。

ctime():返回特定格式的字符串来表示日期时间。

replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond):返回新的datetime对象,值为使用当前参数替换之后的结果。

timetuple ():返回time.struct_time对象,类似于time.localtime()返回的结果。

weekday():返回当前日期是星期几(0 ~ 6)。星期一返回0,星期日返回6。

toordinal():返回当前日期的序数。1年1月1日序数为1,1年1月2日序数为2,以此类推。

strftime(format):根据format指定的格式,显示当前的日期时间对象。

类方法

today():返回当前的日期与时间。

now():返回当前的日期与时间,与today方法类似。

utcnow():返回当前的日期与时间转换为UTC之后的结果。

fromtimestamp(timestamp):从参数指定的timestamp(时间戳,即从新纪元走过的秒数)中创建datetime对象。

utcfromtimestamp(timestamp):从参数指定的timestamp(时间戳,即从新纪元走过的秒数)中创建UTC datetime对象。

fromordinal(ordinal):根据参数指定的ordinal(序数)创建datetime对象。

strptime(date_string, format):根据给定的date_string(日期时间字符串),按照format指定的格式进行解析,返回datetime对象。

(4)timedelta类

timedelta对象用来表示持续时间,可以用来进行日期与时间的加减。

构造器;timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0):根据给定的参数,创建timedelta对象,表示持续时间。持续时间为各参数累计相加。

两个datetime.datetime类型相减 或两个 datetime.date类型相减 的结果就是datetime.timedelta类型

3.5 sys

sys模块提供一些与解释器相关的功能。sys提供的属性很多,不过多数并不常用,常见属性如下:

名称 描述

argv

返回一个列表,列表的第一个元素为命令行运行的文件名称,往后的每个元素为命令行在文件名称后面传递的每一个参数。当我们要进行一些全局性,系统相关的配置时,就可以使用命令行来传递参数。所传递的参数就可以通过argv来进行获取。

version

返回Python的版本信息

copyright

返回Python的版权信息

path

返回模块的搜索路径

float_info

返回浮点类型(float)的相关信息

platform

返回操作系统信息

exit()

退出Python解释器,终止程序的执行

getsizeof(object)

返回object(对象)的大小(以字节为单位)

setrecursionlimit(n)

设置最大递归的深度

 

 

发布了76 篇原创文章 · 获赞 9 · 访问量 5474

猜你喜欢

转载自blog.csdn.net/weixin_43786255/article/details/103057992