Python自定义模块

自定义模块

自定义模块(也就是私人订制),我们要自定义模块,首先就要知道什么是模块

一个函数封装一个功能,比如现在有一个软件,不可能将所有程序都写入一个文件,所以咱们应该分文件,组织结构要好,代码不冗余,所以要分文件,但是分文件,分了5个文件,每个文件里面可能都有相同的功能(函数),怎么办?所以将这些相同的功能封装到一个文件中.
模块就是文件,存放一堆函数,谁用谁拿。怎么拿?
模块是一系列常用功能的集合体,一个py文件就是一个模块

为什么要使用模块?

1、从文件级别组织程序,更方便管理
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用

2、拿来主义,提升开发效率
同样的原理,我们也可以下载别人写好的模块然后导入到自己的项目中使用,这种拿来主义,可以极大地提升我们的开发效率,避免重复造轮子。

ps:
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python meet.py方式去执行,此时meet.py被称为脚本script。

1''' 2-*- coding: utf-8 -*- 3@Author : Meet 4@Software: PyCharm 5@File : meet.py 6''' 7print('from the meet.py') 8 9name = 'guoboayuan' 10 11def read1(): 12 print('meet模块:',name) 13 14def read2(): 15 print('meet模块') 16 read1() 17 18def change(): 19 global name 20 name = 'meet'

导入

import 翻译过来是一个导入的意思

1模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行 2import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是: 3第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句), 4如下 5 6import spam #只在第一次导入时才执行meet.py内代码,此处的显式效果是只打印一次'from the meet.py',当然其他的顶级代码也都被执行了, 只不过没有显示效果.

代码示例:

1import meet 2import meet 3import meet 4import meet 5import meet 6 7执行结果: 只打印一次 8from the meet.py

  每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,
就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突

示例:

当前是meet.py

1import meet 2 3name = 'alex' 4print(name) 5print(meet.name) 6''' 7结果: 8from the meet.py 9alex 10guoboayuan 11''' 12import meet 13def read1(): 14 print(666) 15meet.read1() 16''' 17from the meet.py 18meet模块: guoboayuan 19''' 20import meet 21name = '日天' 22meet.change() 23print(name) 24print(meet.name) 25''' 26from the meet.py 27日天 28宝元 29'''

为模块起别名

别名其实就是一个绰号,好处可以将很长的模块名改成很短,方便使用.

1import meet.py as t 2t.read1()

有利于代码的扩展和优化

1#mysql.py 2def sqlparse(): 3 print('from mysql sqlparse') 4#oracle.py 5def sqlparse(): 6 print('from oracle sqlparse') 7 8#test.py 9db_type=input('>>: ') 10if db_type == 'mysql': 11 import mysql as db 12elif db_type == 'oracle': 13 import oracle as db 14 15db.sqlparse()

导入多个模块

1import os,sys,json 这样写可以但是不推荐 2推荐写法 3 4import os 5import sys 6import json

多行导入:易于阅读 易于编辑 易于搜索 易于维护

from ... import ...

from...import...使用

1from meet import name, read1 2print(name) 3read1() 4''' 5执行结果: 6from the meet.py 7guoboayuan 8meet模块: guoboayuan 9'''

from...import... 与import对比

唯一的区别就是:使用from...import...则是将spam中的名字直接导入到当前的名称空间中,所以在当前名称空间中,
直接使用名字就可以了、无需加前缀:meet.

from...import...的方式有好处也有坏处
​ 好处:使用起来方便了
​ 坏处:容易与当前执行文件中的名字冲突

示例演示:

1.执行文件有与模块同名的变量或者函数名,会有覆盖效果。

1name = 'oldboy' 2from meet import name, read1, read2 3print(name) 4''' 5执行结果: 6from the meet.py 7guoboayuan 8''' 9from meet import name, read1, read2 10name = 'oldboy' 11print(name) 12 13''' 14执行结果: 15oldboy 16 17''' 18def read1(): 19 print(666) 20from meet import name, read1, read2 21read1() 22 23''' 24执行结果: 25from the meet.py 26meet模块: guoboayuan 27''' 28from meet import name, read1, read2 29def read1(): 30 print(666) 31read1() 32 33''' 34执行结果: 35from the meet.py 36666 37'''

2.当前位置直接使用read1和read2就好了,执行时,仍然以spam.py文件全局名称空间

1#测试一:导入的函数read1,执行时仍然回到meet.py中寻找全局变量name 2#test.py 3from meet import read1 4name = 'alex' 5read1() 6''' 7执行结果: 8from the meet.py 9meet--> read1 --> guobaoyuan 10''' 11#测试二:导入的函数read2,执行时需要调用read1(),仍然回到meet.py中找read1() 12#test.py 13from meet import read2 14def read1(): 15 print('==========') 16read2() 17 18''' 19执行结果: 20from the meet.py 21meet --> read2 --> 'meet模块' --> read1 -->'guobaoyuan' 22'''

from导入的模式也支持as

1from meet import read1 as read 2read()

from导入的时候,一行导入多个内容

from meet import read1,read2,name

全部导入

1from meet import * 2#from spam import * 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置 3 4#大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。 5可以使用__all__来控制*(用来发布新版本),在meet.py中新增一行 6__all__=['money','read1'] #这样在另外一个文件中用from spam import *就这能导入列表中规定的两个名字

模块循环导入问题

模块循环/嵌套导入抛出异常的根本原因是由于在python中模块被导入一次之后,就不会重新导入,只会在第一次导入时执行模块内代码

在我们的项目中应该尽量避免出现循环/嵌套导入,如果出现多个模块都需要共享的数据,可以将共享的数据集中存放到某一个地方

在程序出现了循环/嵌套导入后的异常分析、解决方法如下(了解,以后尽量避免)

示范文件内容如下

1#创建一个m1.py 2print('正在导入m1') 3from m2 import y 4 5x='m1' 6 7#创建一个m2.py 8print('正在导入m2') 9from m1 import x 10 11y='m2' 12 13#创建一个run.py 14import m1 15 16#测试一 17执行run.py会抛出异常 18正在导入m1 19正在导入m2 20Traceback (most recent call last): 21 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/aa.py", line 1, in <module> 22 import m1 23 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module> 24 from m2 import y 25 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module> 26 from m1 import x 27ImportError: cannot import name 'x' 28 29 30#测试一结果分析 31先执行run.py--->执行import m1,开始导入m1并运行其内部代码--->打印内容"正在导入m1" 32--->执行from m2 import y 开始导入m2并运行其内部代码--->打印内容“正在导入m2”--->执行from m1 import x,由于m1已经被导入过了,所以不会重新导入,所以直接去m1中拿x,然而x此时并没有存在于m1中,所以报错 33 34 35#测试二:执行文件不等于导入文件,比如执行m1.py不等于导入了m1 36直接执行m1.py抛出异常 37正在导入m1 38正在导入m2 39正在导入m1 40Traceback (most recent call last): 41 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module> 42 from m2 import y 43 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module> 44 from m1 import x 45 File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module> 46 from m2 import y 47ImportError: cannot import name 'y' 48 49 50#测试二分析 51执行m1.py,打印“正在导入m1”,执行from m2 import y ,导入m2进而执行m2.py内部代码--->打印"正在导入m2",执行from m1 import x,此时m1是第一次被导入,执行m1.py并不等于导入了m1,于是开始导入m1并执行其内部代码--->打印"正在导入m1",执行from m1 import y,由于m1已经被导入过了,所以无需继续导入而直接问m2要y,然而y此时并没有存在于m2中所以报错 52 53 54 55# 解决方法: 56方法一:导入语句放到最后 57#m1.py 58print('正在导入m1') 59 60x='m1' 61 62from m2 import y 63 64#m2.py 65print('正在导入m2') 66y='m2' 67 68from m1 import x 69 70方法二:导入语句放到函数中 71#m1.py 72print('正在导入m1') 73 74def f1(): 75 from m2 import y 76 print(x,y) 77 78x = 'm1' 79 80# f1() 81 82#m2.py 83print('正在导入m2') 84 85def f2(): 86 from m1 import x 87 print(x,y) 88 89y = 'm2' 90 91#run.py 92import m1 93 94m1.f1()

模块的重载(了解)

考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块,

有的同学可能会想到直接从sys.module中删除一个模块不就可以卸载了吗,注意了,你删了sys.module中的模块对象仍然可能被其他程序的组件所引用,因而不会被清楚。

特别的对于我们引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。

py文件的两种功能

1#编写好的一个python文件可以有两种用途: 2 一:脚本,一个文件就是整个程序,用来被执行 3 二:模块,文件中存放着一堆功能,用来被导入使用 4 5 6#python为我们内置了全局变量__name__, 7 当文件被当做脚本执行时:__name__ 等于'__main__' 8 当文件被当做模块导入时:__name__等于模块名 9 10#作用:用来控制.py文件在不同的应用场景下执行不同的逻辑(或者是在模块文件中测试代码) 11if __name__ == '__main__': 12print('from the meet.py') 13 14__all__ = ['name', 'read1', ] 15 16name = 'guobaoyuan' 17 18 19def read1(): 20 print('meet模块:', name) 21 22 23def read2(): 24 print('meet模块') 25 read1() 26 27 28def change(): 29 global name 30 name = '宝元' 31 32 33if __name__ == '__main__': 34 # 在模块文件中测试read1()函数 35 # 此模块被导入时 __name__ 就变成了文件名,if条件不成立 36 # 所以read1不执行 37 read1()

模块的搜索路径

模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

1#模块的查找顺序 21、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用 3 ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看 42、如果没有,解释器则会查找同名的内建模块 53、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。 6 7#需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。 8 9#在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。 10>>> import sys 11>>> sys.path.append('/a/b/c/d') 12>>> sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索 13注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找. 14 15#windows下的路径不加r开头,会语法错误 16sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\a')

编译Python文件(了解)

为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度。python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式为:module.version.pyc。通常会包含python的版本号。例如,在CPython3.3版本下,spam.py模块会被缓存成__pycache__/spam.cpython-33.pyc。这种命名规范保证了编译后的结果多版本共存。

Python检查源文件的修改时间与编译的版本进行对比,如果过期就需要重新编译。这是完全自动的过程。并且编译的模块是平台独立的,所以相同的库可以在不同的架构的系统之间共享,即pyc使一种跨平台的字节码,类似于JAVA火.NET,是由python虚拟机来执行的,但是pyc的内容跟python的版本相关,不同的版本编译后的pyc文件不同,2.5编译的pyc文件不能到3.5上执行,并且pyc文件是可以反编译的,因而它的出现仅仅是用来提升模块的加载速度的,不是用来加密的。

1#提示: 21.模块名区分大小写,foo.py与FOO.py代表的是两个模块 32.在速度上从.pyc文件中读指令来执行不会比从.py文件中读指令执行更快,只有在模块被加载时,.pyc文件才是更快的 43.只有使用import语句是才将文件自动编译为.pyc文件,在命令行或标准输入中指定运行脚本则不会生成这类文件.

time模块

time翻译过来就是时间,有我们其实在之前编程的时候有用到过.

1#常用方法 21.time.sleep(secs) 3(线程)推迟指定的时间运行。单位为秒。 42.time.time() 5获取当前时间戳

在计算中时间共有三种方式:

1.时间戳: 通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型

2.格式化字符串时间: 格式化的时间字符串(Format String): ‘1999-12-06’

1python中时间日期格式化符号: 2%y 两位数的年份表示(00-993%Y 四位数的年份表示(000-99994%m 月份(01-125%d 月内中的一天(0-316%H 24小时制小时数(0-237%I 12小时制小时数(01-128%M 分钟数(00=599%S 秒(00-5910%a 本地简化星期名称 11%A 本地完整星期名称 12%b 本地简化的月份名称 13%B 本地完整的月份名称 14%c 本地相应的日期表示和时间表示 15%j 年内的一天(001-36616%p 本地A.M.P.M.的等价符 17%U 一年中的星期数(00-53)星期天为星期的开始 18%w 星期(0-6),星期天为星期的开始 19%W 一年中的星期数(00-53)星期一为星期的开始 20%x 本地相应的日期表示 21%X 本地相应的时间表示 22%Z 当前时区的名称 23%% %号本身

3.结构化时间:元组(struct_time) struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

首先,我们先导入time模块,来认识一下python中表示时间的几种格式:

1#导入时间模块 2>>>import time 3 4#时间戳 5>>>time.time() 61500875844.800804 7 8#时间字符串 9>>>time.strftime("%Y-%m-%d %X") 10'2017-07-24 13:54:37' 11>>>time.strftime("%Y-%m-%d %H-%M-%S") 12'2017-07-24 13-55-04' 13 14#时间元组:localtime将一个时间戳转换为当前时区的struct_time 15time.localtime() 16time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, 17          tm_hour=13, tm_min=59, tm_sec=37, 18 tm_wday=0, tm_yday=205, tm_isdst=0)

小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的

时间格式转换:

img

1#时间戳-->结构化时间 2#time.gmtime(时间戳) #UTC时间,与英国伦敦当地时间一致 3#time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间 4>>>time.gmtime(1500000000) 5time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0) 6>>>time.localtime(1500000000) 7time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0) 8 9 10 11#结构化时间-->时间戳  12#time.mktime(结构化时间) 13>>>time_tuple = time.localtime(1500000000) 14>>>time.mktime(time_tuple) 151500000000.0 16 17 18 19#结构化时间-->字符串时间 20#time.strftime("格式定义","结构化时间") 结构化时间参数若不传,则显示当前时间 21>>>time.strftime("%Y-%m-%d %X") 22'2017-07-24 14:55:36' 23>>>time.strftime("%Y-%m-%d",time.localtime(1500000000)) 24'2017-07-14' 25 26 27 28#字符串时间-->结构化时间 29#time.strptime(时间字符串,字符串对应格式) 30>>>time.strptime("2017-03-16","%Y-%m-%d") 31time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1) 32>>>time.strptime("07/24/2017","%m/%d/%Y") 33time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

img

1#结构化时间 --> %a %b %d %H:%M:%S %Y2#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串 3>>>time.asctime(time.localtime(1500000000)) 4'Fri Jul 14 10:40:00 2017' 5>>>time.asctime() 6'Mon Jul 24 15:18:33 2017' 7 8 9 10#时间戳 --> %a %b %d %H:%M:%S %Y11#time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串 12>>>time.ctime() 13'Mon Jul 24 15:19:07 2017' 14>>>time.ctime(1500000000) 15'Fri Jul 14 10:40:00 2017'

我们看完了time在来看一个Python处理日期和时间的标准库

datetime

获取当前日期和时间

1from datetime import datetime 2 3print(datetime.now()) 4 5''' 6结果:2018-12-04 21:07:48.734886 7'''

注意:datetime是模块,datetime模块还包含一个datetime的类,通过from datetime import datetime导入的才是datetime这个类。

如果仅导入import datetime,则必须引用全名datetime.datetime

datetime.now()返回当前日期和时间,其类型是datetime

获取指定日期和时间

要指定某个日期和时间,我们直接用参数构造一个datetime

1from datetime import datetime 2 3dt = datetime(2018,5,20,13,14) 4print(dt) 5 6''' 7结果:2018-05-20 13:14:00 8'''

datetime转换为timestamp(时间戳)

1from datetime import datetime 2 3dt = datetime.now() 4new_timestamp = dt.timestamp() 5print(new_timestamp) 6 7''' 8结果:1543931750.415896 9'''

timestamp转换为datetime

1import time 2from datetime import datetime 3 4new_timestamp = time.time() 5print(datetime.fromtimestamp(new_timestamp))

str转换为datetime

很多时候,用户输入的日期和时间是字符串,要处理日期和时间,首先必须把str转换为datetime。转换方法是通过datetime.strptime()实现,需要一个日期和时间的格式化字符串:

1from datetime import datetime 2 3t = datetime.strptime('2018-4-1 00:00','%Y-%m-%d %H:%M') 4print(t) 5''' 6结果: 2018-04-01 00:00:00 7'''

datetime转换为str

如果已经有了datetime对象,要把它格式化为字符串显示给用户,就需要转换为str,转换方法是通过strftime()实现的,同样需要一个日期和时间的格式化字符串:

1from datetime import datetime 2now = datetime.now() 3print(now.strftime('%a, %b %d %H:%M')) 4Mon, May 05 16:28

datetime加减

对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+-运算符,不过需要导入timedelta这个类:

1from datetime import datetime, timedelta 2now = datetime.now() 3print(now) 4now1 = now + timedelta(hours=10) 5print(now1) 6now2 = now - timedelta(days=1) 7print(now2) 8now3 = now + timedelta(days=2, hours=12) 9print(now3)

可见,使用timedelta你可以很容易地算出前几天和后几天的时刻。

小结注意

datetime表示的时间需要时区信息才能确定一个特定的时间,否则只能视为本地时间。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Python基础4——模块与包

12模块与包模块通俗地理解为.py文件,里面定义了变量、函数和类。需要的时候就可以导入这些模块。执行步骤1.在python模块加载路径中查找相应的模块文件2.将模块文件编译成中间代码3.执行模块文件中的代码12.1模块分类1.内置模块,也叫标准库,比如说random,time,大概有200多个2.第三方模块,也称为第三方库,使用pipins

浅析Python模块的引入和调用

大家好,我是IT共享者,人称皮皮。这篇文章我们来浅析Python模块的引入和调用。一、前言Python中的模块,有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt函数,必须用语句include引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些其他的函数,该怎么处理呢?在Python中有一个概念叫做模块(mod