饮冰三年-人工智能-Python-17Python基础之模块与包
Posted 逍遥小天狼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了饮冰三年-人工智能-Python-17Python基础之模块与包相关的知识,希望对你有一定的参考价值。
一、模块(module)
1.1 啥是模块
简单理解一个.py文件就称之为一个模块。
有的功能开发者自己无法完成,需要借助已经实现的函数\\类来完成这些功能。例如:和操作系统打交道的类或者是随机数函数等系统内置模块。
有的功能其他开发者已经完成,我们无需重复造轮子,只需借用他们的功能。例如:django框架或者scrapy框架等第三方模块。
有的功能开发者已经自主完成,需要重复使用,可以通过模块避免代码重复。这种称为自定义模块。
1.2 模块种类
# 内置模块 # 安装python解释器的时候跟着装上的那些方法 # 第三方模块/扩展模块 # 没在安装python解释器的时候安装的那些功能 # 自定义模块 # 你写的功能如果是一个通用的功能,那你就把它当做一个模块
1.3 模块的优点
-
分类管理方法
-
节省内存
- 提供更多的功能,避免重复造轮子
1.4 如何使用模块
# import cul #第一种写法 from pkage11.cul import add #第二种写法 if __name__==\'__main__\': print(add()) # import 语句的搜索路径 # [\'\', \'/usr/lib/python3.4\', \'/usr/lib/python3.4/plat-x86_64-linux-gnu\',\'/usr/lib/python3.4/lib-dynload\', \'/usr/local/lib/python3.4/dist-packages\', \'/usr/lib/python3/dist-packages\'] # 区别: # 无论1还是2,首先通过sys.path找到cul.py,然后执行cul脚本(全部执行), # 区别是1会将cul这个变量名加载到名字空间,而2只会将add这个变量名加载进来。
1.5 模块运行的原理
首先,我们要知道py文件运行的两种方式:
- 以脚本的形式运行。如:直接pycharm运行 cmd运行
- 以模块的方式运行。如:import my_module
name = "张三" def sayHi(): print("Hi,I\'m %s" % name) sayHi()
import my_module
被调用处只导入了一个my_module模块,控制台有 # Hi,I\'m 张三 输出。
其次,我们要了解其调用过程 1:找到my_module模块;2:开辟命名空间;3:执行这个模块
结论一:一旦引入模块,该模块就会执行。
PS:同一模块即使import多次,也只是执行1次
问题一:sayHi() 在测试或调试的时候使用,不希望在被调用处运行。
name = "张三" def sayHi(): print("Hi,I\'m %s" % name) if __name__ == \'__main__\': sayHi()
import my_module from my_module import name, sayHi print(name) sayHi() print("---------------------") name = "李四" print(name) sayHi() print("---------------------") #强行修改,被导入模块的值 my_module.name = "王五" print(name) sayHi() print("---------------------") #强行刷新 当前模块的值 from my_module import name print(name) sayHi() \'\'\' 张三 Hi,I\'m 张三 --------------------- 李四 Hi,I\'m 张三 --------------------- 李四 Hi,I\'m 王五 --------------------- 王五 Hi,I\'m 王五 \'\'\'
结论二:如果本文件中和导入的模块中的变量名相同,调用最后一次加载内存中的值。如name的变化。
结论三:强烈不建议调用处使用和被调用同名的变量(可以通过as别名的方式避免),不建议强行修改被调用模块中的变量值或方法内容
from my_module import *:默认是导入该模块下的所有内容
但是如果在my_module中 通过 __all__=["name"]。那么import * 也就只包含name一项内容了。
1.6 __main__与__name__
import sys print(__name__) #__main__ print(sys.modules[__name__]) # <module \'__main__\' from \'D:/Code/Home_ORM/App01/my_module.py\'>
import my_module \'\'\' 输出结果 my_module <module \'my_module\' from \'D:\\\\Code\\\\Home_ORM\\\\App01\\\\my_module.py\'> \'\'\'
结论一: 1.6.1 __name__的变与不变 (变的是位置:如果是在当前其值为__main__,不变的是初心:路径不变)
__main__是当前文件执行地址
import sys print(sys.modules["__main__"]) # <module \'__main__\' from \'D:/Code/Home_ORM/App01/my_module.py\'>
import my_module \'\'\' 输出结果 <module \'__main__\' from \'D:/Code/Home_ORM/App01/tests.py\'> \'\'\'
结论二:__main__:是当前直接执行文件所在的地址
import sys print(sys.modules["__main__"]) # <module \'__main__\' from \'D:/Code/Home_ORM/App01/my_module.py\'> def funa():print("aaa") # getattr(sys.modules[\'__main__\'],"funa")() # __main__在被调用处运行,有可能会由于没有导入funa而导致报错 getattr(sys.modules[__name__],"funa")()
my_module结论三:__main__:使用反射自己模块中的内容的时候都要使用__name__。不能用\'__main__\'。注意__name__不需要加\'\',而\'__main__\'需要
结论四:不要出现循环引用
总结:
- \'__main__\':当前直接执行文件所在的地址
- if __name__==\'__main__\': #主要作用是测试当前模块,不被被调用处运行。
- 在编写py文件的时候,所有不在函数和类中封装的内容都应该写在, if __name__ == \'__main__\':下面
- 使用反射自己模块中的内容的时候都要使用__name__。不能用__main__。 # import sys # getattr(sys.modules[__name__],变量名)
二、包
当提供的功能比较复杂,一个py文件无法完成的时候,我们把结合了一组py文件,提供了一组复杂功能的py集合称为包。下面有__init__.py文件。
1 直接导入模块
import 包.包.模块
包.包.模块.变量
from 包.包 import 模块 # 推荐
模块.变量
2 导入包 读框架源码的时候,封装好让别人使用
如要希望导入包之后 模块能够正常的使用 那么需要自己去完成init文件的开发
包中模块的 绝对导入
包中模块的 相对导入
使用了相对导入的模块只能被当做模块执行
不能被当做脚本执行
三、常用模块
3.1 时间模块
import time #毫秒值--开始 print(time.time()) #输出结果 1538533474.3565 #毫秒值--结束 #结构化时间--开始 print(time.localtime()) #输出结果 time.struct_time(tm_year=2018, tm_mon=10, tm_mday=3, tm_hour=11, tm_min=5, tm_sec=21, tm_wday=2, tm_yday=276, tm_isdst=0) print(time.gmtime()) #输出结果 time.struct_time(tm_year=2018, tm_mon=10, tm_mday=3, tm_hour=3, tm_min=8, tm_sec=19, tm_wday=2, tm_yday=276, tm_isdst=0) #结构化时间--结束 #结构化时间==》毫秒值--开始 print(time.mktime(time.localtime())) #结构化时间==》毫秒值--结束 #结构化时间==》格式化时间--开始 print(time.strftime(\'%Y-%m-%d %X\',time.localtime())) #结构化时间==》格式化时间--结束 #格式化时间==》结构化时间-开始 print(time.strptime(\'2018-10-03 11:18:37\',\'%Y-%m-%d %X\')) #格式化时间==》结构化时间-结束 #固定格式的时间-开始 print(time.asctime()) print(time.ctime()) #固定格式的时间-结束
import datetime print(datetime.datetime.now())
判断一个时间是否是10分钟之内
import time help_alarm_entity = HelpAlarmHistory.objects.filter(sms_code="661").first() # type:HelpAlarmHistory # 获取数据表中的时间字段,并转成秒 d1 = time.mktime(help_alarm_entity.process_time.timetuple()) # 获取当前时间转成秒 d2 = time.mktime(time.localtime()) # 人生,应该做减法 d = d2 - d1 - 600 if d > 0: print("超过10分钟") else: print("10分钟之内") print(\'相差的秒数:{}\'.format(d))
3.2 随机函数
import random ret = random.random() print(ret) ret1 = random.randint(1,3) #[1,3] print(ret1) ret1 = random.randrange(1,3) #[1,3) print(ret1) ret1 = random.choice([1,3,5]) #从1,3,5中获取数据 print(ret1) ret1 = random.sample([1,3,5],2) #从1,3,5中获取2个数据 print(ret1) ret1=[1,3,5] random.shuffle(ret1) #重新洗牌 print(ret1)
def v_code(): ret="" for i in range(5): num= random.randint(0,9) alf=chr(random.randint(65,122)) s=str(random.choice([num,alf])) ret+=s return ret print(v_code())
3.3 OS
import os os.getcwd() # 获取当前工作目录,即当前python脚本工作的目录路径 print(os.getcwd()) # D:\\Code\\venv1 # 改变当前脚本工作目录;相当于shell下cd os.chdir("..") print(os.getcwd()) # os.curdir 返回当前目录: (\'.\') print(os.curdir) # os.pardir 获取当前目录的父目录字符串名:(\'..\') print(os.pardir) # os.makedirs(\'dirname1/dirname2\') 可生成多层递归目录 os.makedirs(\'dirname1/dirname2\') # os.removedirs(\'dirname1\') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.removedirs(\'dirname1/dirname2\') # os.mkdir(\'dirname\') 生成单级目录;相当于shell中mkdir dirname os.mkdir(\'dirname\') # os.listdir(\'dirname\') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.listdir(\'dirname\') # os.rmdir(\'dirname\') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.rmdir(\'dirname\') # os.remove() 删除一个文件 # os.rename("oldname","newname") 重命名文件/目录 os.mkdir(\'dirname\') os.rename(\'dirname\',\'newname\') os.rmdir(\'newname\') # os.stat(\'path/filename\') 获取文件/目录信息 os.mkdir(\'dirname\') print(os.stat(\'D:\\Code\\dirname\')) os.rmdir(\'dirname\') # os.sep 输出操作系统特定的路径分隔符,win下为"\\\\",Linux下为"/" # os.linesep 输出当前平台使用的行终止符,win下为"\\t\\n",Linux下为"\\n" # os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: # os.name 输出字符串指示当前使用平台。win->\'nt\'; Linux->\'posix\' # os.system("bash command") 运行shell命令,直接显示 # os.environ 获取系统环境变量 print(os.environ) # os.path.abspath(path) 返回path规范化的绝对路径 print(os.path.abspath(\'dirname\')) # os.path.split(path) 将path分割成目录和文件名二元组返回 print(os.path.split(\'D:\\Code\\dirname\')) # os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 print(os.path.dirname(\'D:\\Code\\dirname\') ) # os.path.basename(path) 返回path最后的文件名。如何path以/或\\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 print(os.path.basename(\'dirname\') ) os.mkdir(\'dirname\') # os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False print(os.path.exists(\'D:\\Code\\dirname\') ) # os.path.isabs(path) 如果path是绝对路径,返回True print(os.path.exists(\'D:\\Code\\dirname\') ) # os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False print(os.path.isfile(\'D:\\Code\\dirname\') ) # os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False print(os.path.isdir(\'D:\\Code\') ) os.rmdir(\'dirname\') # os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 s="D:\\Code" n="dirname" print(os.path.join(s,n) ) os.mkdir(\'dirname\') # os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 print(os.path.getatime(\'D:\\Code\\dirname\') ) # os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 print(os.path.getmtime(\'D:\\Code\\dirname\') ) os.rmdir(\'dirname\')
3.4 Json
# ----------------------------序列化 import json dic = {\'name\': \'alvin\', \'age\': 23, \'sex\': \'male\'} print(type(dic)) # <class \'dict\'> j = json.dumps(dic) print(type(j)) # <class \'str\'> print(j) #{"name": "alvin", "age": 23, "sex": "male"} 把单引号修改成了双引号 data=json.loads(j) print(data) #{\'name\': \'alvin\', \'age\': 23, \'sex\': \'male\'}
3.5 pickle
##----------------------------序列化 import pickle dic={\'name\':\'alvin\',\'age\':23,\'sex\':\'male\'} print(type(dic))#<class \'dict\'> j=pickle.dumps(dic) print(type(j))#<class \'bytes\'> f=open(\'序列化对象_pickle\',\'wb\')#注意是w是写入str,wb是写入bytes,j是\'bytes\' f.write(j) #-------------------等价于pickle.dump(dic,f) f.close() #-------------------------反序列化 import pickle f=open(\'序列化对象_pickle\',\'rb\') data=pickle.loads(f.read())# 等价于data=pickle.load(f) print(data[\'age\'])
3.6 shelve
import shelve f=shelve.open(r\'shelve2\') #目的:将一个字典放入到文本中,二进制,是二进制啊 f["stu1_info"]={\'name\':\'ajax\',\'age\':\'12\'} f["school_info"]={\'name\':\'北大青鸟\',\'city\':\'beijing\'} f.close() f=shelve.open(r\'shelve2\') print(f.get(\'stu1_info\')[\'age\']) #会生成3个文件 # shelve2.bak # shelve2.dat # shelve2.dir
3.7 xml
<data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year updated="yes">2013</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year updated="yes">2016</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="China"> <rank updated="yes" /> <year>2018</year><gdppc /> <neighbor /> </country> </data>
#操作xml import xml.etree.ElementTree as ET # 1加载xml数据 tree = ET.parse("htmlContent.html") # 2获取根节点 root = tree.getroot(); print(root.tag) #data #3 查询 #3.1 遍历xml文档 for child in root: print(child.tag,child.attrib) #country {\'name\': \'Liechtenstein\'} for i in child: print(i.tag,i.attrib,i.text) #3.2 只遍历year 节点 for node in root.iter(\'year\'): print(node.tag,node.attrib,node.text) #4 修改 for node in root.iter(\'year\'): new_year = int(node.text)+1 node.text=str(new_year) node.set("updated","yes") tree.write("htmlContent.html") #5 删除 for node in root.findall(\'country\'): rank = int(node.find("rank").text) if rank > 50: root.remove(node) tree.write("htmlContent.html") #6 添加节点 country = ET.SubElement(root,"country",attrib={"name":"China"以上是关于饮冰三年-人工智能-Python-17Python基础之模块与包的主要内容,如果未能解决你的问题,请参考以下文章
饮冰三年-人工智能-Python-22 Python初始Django
饮冰三年-人工智能-Python-12之利其器pycharm