Python【day6】:Python学习(xml-2 yaml-3 shutil-1 logging-7 Subprocess-6 hashlib-5 configparser-4 shelve 模块和面向对象介绍)
xml处理模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
1、读取遍历xml格式文档
__author__ = 'Administrator' #-*- coding:utf-8 -*- #1读取遍历xml格式文档 import xml.etree.ElementTree as ET #1打印根节点 tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #data #2遍历xml文档(只打印第一层节点) for child in root: print(child.tag,child.attrib) # for i in child: # print(i.tag,i.text) # country {'name': 'Liechtenstein'} # country {'name': 'Singapore'} # country {'name': 'Panama'} #3遍历xml文档(打印第一、二层节点) for child in root: #外循环 print(child.tag,child.attrib) #标签 属性 for i in child: #内循环 print(i.tag,i.text) #标签 文本 # country {'name': 'Liechtenstein'} # rank 2 # year 2008 # gdppc 141100 # neighbor None # neighbor None # country {'name': 'Singapore'} # rank 5 # year 2011 # gdppc 59900 # neighbor None # country {'name': 'Panama'} # rank 69 # year 2011 # gdppc 13600 # neighbor None # neighbor None #4只遍历year节点(把标签是year的都过滤出来) for node in root.iter("year"): #iter相当于过滤 print(node.tag,node.text) # year 2008 # year 2011 # year 2011
2、修改和删除xml文档
__author__ = 'Administrator' #-*- coding:utf-8 -*- #2修改和删除xml文档 import xml.etree.ElementTree as ET #1修改xml的字段(year字段的值+1) tree = ET.parse("xmltest.xml") #解析xml文件成文件树 Parse XML document into element tree. root = tree.getroot() # print(root) #<Element 'data' at 0x0000000000B5F868> 内存地址 for node in root.iter("year"): #将year字段过滤出来 new_year = int(node.text) +1 #将year对应的值text转换成int后,加1 node.text = str(new_year) #将int转换成str node.set("updated","yes") #设置year字段的属性 updated="yes" print(node.tag,node.text) #打印year标签,打印year标签的值 tree.write("xmltest.xml") #将修改后的year写入到xml文件 #2删除xml的其中一个节点 for i in root.findall("country"): #找到所有的标签“country” rank = int(i.find("rank").text) #在country节点下,找到rank节点的值,并转换成int,用于比较运算 if rank >50: root.remove(i) #删除节点 tree.write("xmltest2.xml") ##将删除节点后的内容写入到xml文件 #3如何在已有xml的文件添加新的节点?
3、创建xml文档
__author__ = 'Administrator' #-*- coding:utf-8 -*- #3创建xml文档 import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") #根节点(一级节点)的名字是 namelist name = ET.SubElement(new_xml,"name",attrib = {"enrolled":"yes"}) #二级节点1 标签和属性 age = ET.SubElement(name,"age",attrib = {"checked":"no"}) #三级节点 字段名字和属性 sex = ET.SubElement(name,"sex") #三级节点 字段名字 不指定属性 age.text = "33" #指定三级节点 字段名字对应的值 sex.text = "male" #指定三级节点 字段名字对应的值 name2 = ET.SubElement(new_xml,"name",attrib = {"enrolled":"yes"}) #二级节点2 标签和属性 age = ET.SubElement(name2,"age",attrib = {"checked":"no"}) sex = ET.SubElement(name2,"sex") age.text = "19" sex.text = "female" et = ET.ElementTree(new_xml) #生产文档对象 et.write("test.xml",encoding = "utf-8",xml_declaration=True) #写入到文件test.xml ET.dump(new_xml) #打印生成的格式 #问题:创建后的xml文件没有缩进?需要手动调整,怎么在文件中自动缩进换行?
ConfigParser模块
用于生成和修改常见配置文档
1、新建configparser文件
__author__ = 'Administrator' #-*- coding:utf-8 -*- import configparser #1新建configparser文件 config = configparser.ConfigParser() config["DEFAULT"] = {"ServerAliveInterval":"45", "Compression":"yes", "CompressionLevel":"9"} #0写入默认section config["bitbucket.org"] = {} #1写入section1 config["bitbucket.org"]["User"] = "hg" #2写入键值对(key-value) config["topsecret.server.com"] = {} #1写入section2 config["topsecret.server.com"]["Host Port"] = "50022" #2写入键值对1(key-value) config["topsecret.server.com"]["ForwardX11"] = "no" #3写入键值对2(key-value) config['DEFAULT']['ForwardX11'] = 'yes' #4往默认section中添加键值对 config["topsecret.server.com"]["ForwardX12"] = "no" #4往section2中添加键值对 with open("example.ini","w") as configfile: config.write(configfile)
2、读取configparser文件到内存
__author__ = 'Administrator' #-*- coding:utf-8 -*- #2读取configparser文件到内存 import configparser config = configparser.ConfigParser() print(config.sections()) #[] #1将文件名打印出来 print(config.read("example.ini")) #['example.ini'] #2将文件中的section读取出来后,是存在列表中的(默认的section是读不出来的) print(config.sections()) #['bitbucket.org', 'topsecret.server.com'] #3判断某个section是否在config print("bitbucket.org" in config) #True print("bitbucket1.org" in config) #False #4取出section中键对应的值--类似于字典(多了一个section) print(config["bitbucket.org"]["user"]) #hg print(config["DEFAULT"]["Compression"]) #yes print(config["topsecret.server.com"]["host port"]) #50022 print(config["topsecret.server.com"]["forwardx11"]) #no #5遍历输出key--这里的key包含DEFAULT中的key(注意:DEFAULT必须大写才能输出默认的key,小写的话,就不输出默认的key) for i in config["topsecret.server.com"]: print(i) # host port # forwardx11 # forwardx12 # serveraliveinterval # compressionlevel # compression
3、configparser增删改查语法
__author__ = 'Administrator' #-*- coding:utf-8 -*- import configparser #03configparser增删改查语法 #1读--查--读出到内存 config = configparser.ConfigParser() config.read('config.cfg') #读文件 #2将文件中的所有section读取出来后,是存在列表中的(默认Default-大写的section是读不出来的) print(config.sections()) #['bitbucket.org', 'topsecret.server.com'] #3将bitbucket.org这个section下的key以及默认的key读取出来,存在列表中 print(config.options("bitbucket.org")) #['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11'] #4将bitbucket.org这个section下的key-value以及默认的key-value读取出来,作为元组,存在列表中 print(config.items("bitbucket.org")) #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')] #5将bitbucket.org这个section下的key对应的value读出来 print(config.get('bitbucket.org','User')) #hg #6将topsecret.server.com这个section下的key对应的value读出来(数字就转换成整数) print(config.getint('topsecret.server.com','port')) #50022 #2增加-section # 1判断"wupeiqi"是否在sections中 print(config.has_section('wupeiqi')) #False config.add_section('wupeiqi') #添加"wupeiqi"到sections中 config.write(open('config.cfg', "w")) #2 增加键值对--类似给字典的键赋值 config["bitbucket.org"]["User1"] = "hg1" config["topsecret.server.com"]["forwardx11"] = "no" #3删除-section print(config.has_section('wupeiqi')) print(config.sections()) #['bitbucket.org', 'topsecret.server.com', 'wupeiqi'] config.remove_section("wupeiqi") #只是内存中删除了,但是文件并没有删除"wupeiqi" print(config.sections()) #['bitbucket.org', 'topsecret.server.com'] config.write(open('config.cfg', "w")) #将内存中删除后,写入到文件 #3-2删除键值对 print(config.options("topsecret.server.com")) config.remove_option('topsecret.server.com','forwardx11') #删除section下对应的键值对 print(config.options("topsecret.server.com")) config.write(open('config.cfg', "w")) #重新写入到文件 #4 修改section下的键值--section无法修改 config.set('bitbucket.org','user',"11111") #将内存中"user"对应的值改成了"111111",但是文件并没有改 print(config.items("bitbucket.org")) #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), # ('forwardx11', 'yes'), ('user', '11111'), ('user1', 'hg1')] config.write(open('config.cfg', "w")) #重新写入到文件,文件内容进行了修改
hashlib模块
用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
__author__ = 'Administrator' #-*- coding:utf-8 -*- #用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 import hashlib #1 md5方式加密 m = hashlib.md5() # m.update("hello") #TypeError: Unicode-objects must be encoded before hashing m.update(b"hello") #这里必须加上b,否则报错 print(m.hexdigest()) #16进制格式hash 5d41402abc4b2a76b9719d911017c592 md5将hello加密后,用16进制显示加密后字符串 print(m.digest()) #2进制格式hash b']A@*\xbcK*v\xb9q\x9d\x91\x10\x17\xc5\x92' hash1 = hashlib.md5() # hash.update('admin') hash1.update(b'admin') #这里必须加上b,否则报错 print(hash1.hexdigest()) #16进制格式hash 21232f297a57a5a743894a0e4a801fc3 print(len(hash1.hexdigest())) #32位 # 2 sha1方式加密 hash1 = hashlib.sha1() # hash1.update('admin') #TypeError: Unicode-objects must be encoded before hashing hash1.update(b'admin') #这里必须加上b,否则报错 print(hash1.hexdigest()) #16进制格式 d033e22ae348aeb5660fc2140aec35850c4da997 print(len(hash1.hexdigest())) #40位 # 3 sha256方式加密 hash1 = hashlib.sha256() # hash1.update('admin') #TypeError: Unicode-objects must be encoded before hashing hash1.update(b'admin') #这里必须加上b,否则报错 print(hash1.hexdigest()) #16进制格式 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 print(len(hash1.hexdigest())) #64位 # 4 sha384方式加密 hash1 = hashlib.sha384() # hash1.update('admin') #TypeError: Unicode-objects must be encoded before hashing hash1.update(b'admin') #这里必须加上b,否则报错 print(hash1.hexdigest()) #16进制格式 9ca694a90285c034432c9550421b7b9dbd5c0f4b6673f05f6dbce58052ba20e4248041956ee8c9a2ec9f10290cdc0782 print(len(hash1.hexdigest())) #96位 # 5 sha512方式加密 hash1 = hashlib.sha512() # hash1.update('admin') #TypeError: Unicode-objects must be encoded before hashing hash1.update(b'admin') #这里必须加上b,否则报错 print(hash1.hexdigest()) #16进制格式 c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec print(len(hash1.hexdigest())) #128位 #6 以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。 # 所以,有必要对加密算法中添加自定义key再来做加密。 hash1 = hashlib.md5(b'898oaFs09f') hash1.update(b'admin') print(hash1.hexdigest()) #16进制格式 67929daefab29024d18340945036e291 print(len(hash1.hexdigest())) #32位
应用场景:微信登录,后台密码是用md5密文存储的(加密后,不能直接反解)
用户微信登录的时候,输入的密文密码,通过md5加密后,转换成密文,和数据库存储的密文对比,是一样的,就允许登录
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志从低到高可以分为 debug(), info(), warning(), error() and critical() 5个级别
#1 最简单用法
import logging
logging.debug("wrong password more than 1 times") #日志不输出
logging.info("wrong password more than 2 times") #日志不输出
logging.warning("wrong password more than 3 times")
logging.error("wrong password more than 4 times")
logging.critical("server is down")
# WARNING:root:wrong password more than 3 times
# ERROR:root:wrong password more than 4 times
# CRITICAL:root:server is down
2、写日志到文件
__author__ = 'Administrator' #-*- coding:utf-8 -*- import logging # 如果想把日志写到文件里 #1 日志写到文件中,加上日期时间 应用场景:集中记录日志的需求 # logging.basicConfig(filename="example.log",level = logging.INFO,format="%(levelno)s %(asctime)s %(message)s",datefmt="%Y-%m-%d %H:%M:%S") #INFO必须大写,否则报错,日志级别是INFO,所以debug日志不会写入到文件,要把debug日志写入到文件,需要修改日志级别成DEBUG logging.basicConfig(filename="example.log",level = logging.INFO, format="%(msg)s-%(msecs)s-%(module)s-%(levelno)s-%(created)s-%(asctime)s-%(name)s-%(levelname)s-%(message)s-%(filename)s" ,datefmt="%Y-%m-%d %H:%M:%S") logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too') #So should this-985.7749938964844-02 writelog_file-20-1456154694.985775-2016-02-22 23:24:54-root-INFO-So should this-02 writelog_file.py #And this, too-985.7749938964844-02 writelog_file-30-1456154694.985775-2016-02-22 23:24:54-root-WARNING-And this, too-02 writelog_file.py #%(name)s 指的是 TEST-LOG # %(asctime)s指的是日志时间 2016-02-22 22:55:24 # %(levelname)s 指的是日志级别 WARNING # %(message)s 指的是日志信息 warn message # %(filename)s可以区别是哪个模块输出的日志 03 writefileview.py(带py) # %(created)s 指的时间戳1456153718.13236 # %(levelno)s 指的日志级别的分数 debug-10, info-20, warning-30, error-40 and critical-50 # %(module)s 03 writefileview(不带py) # %(msecs)s 指的是时间得毫秒 # %(pathname)s 显示当前文件的绝对路径 # D:/PycharmProjects/s12/day6_0220/03 xiaojie/05 logging模块/03 writefileview.py-
3、想同时把log打印在屏幕和文件日志里
__author__ = 'Administrator' #-*- coding:utf-8 -*- # logging的日志可以从低到高依次分为 debug(), info(), warning(), error() and critical() 5个级别 # 级别越高,显示日志越少 # 想同时把log打印在屏幕和文件日志里 import logging logger = logging.getLogger("TEST-LOG") #创建日志对象 logger.setLevel(logging.DEBUG) #定义全局日志级别(DEBUG必须大写) sh = logging.StreamHandler() #创建屏幕句柄--全局日志级别和屏幕日志级别,按级别高的来 sh.setLevel(logging.DEBUG) #定义屏幕打印日志级别(DEBUG必须大写) fh = logging.FileHandler("access.log") #创建文件句柄--全局日志级别和文件日志级别,按级别高的来 fh.setLevel(logging.WARNING) #定义文件中日志级别(WARNING必须大写) formatter= logging.Formatter("%(msg)s-%(msecs)s-%(module)s-%(levelno)s-%(created)s-%(asctime)s-%(name)s-%(levelname)s-%(message)s-%(filename)s") #定义日志格式 #%(name)s 指的是 TEST-LOG # %(asctime)s指的是日志时间 2016-02-22 22:55:24 # %(levelname)s 指的是日志级别 WARNING # %(message)s 指的是日志信息 warn message # %(filename)s可以区别是哪个模块输出的日志 03 writefileview.py(带py) # %(created)s 指的时间戳1456153718.13236 # %(levelno)s 指的日志级别的分数 debug-10, info-20, warning-30, error-40 and critical-50 # %(module)s 03 writefileview(不带py) # %(msecs)s 指的是时间得毫秒 # %(pathname)s 显示当前文件的绝对路径 # D:/PycharmProjects/s12/day6_0220/03 xiaojie/05 logging模块/03 writefileview.py- sh.setFormatter(formatter) #添加日志格式到屏幕句柄 fh.setFormatter(formatter) #添加日志格式到文件句柄 logger.addHandler(sh) #添加屏幕句柄到日志对象 logger.addHandler(fh) #添加文件句柄到日志对象 logger.debug('debug message') #注意,这里是logger不能是logging,否则输出不对 logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message') # 2016-02-22 23:04:14,982-TEST-LOG-DEBUG-debug message-03 writefileview.py # 2016-02-22 23:04:14,982-TEST-LOG-INFO-info message-03 writefileview.py # 2016-02-22 23:04:14,982-TEST-LOG-WARNING-warn message-03 writefileview.py # 2016-02-22 23:04:15,017-TEST-LOG-ERROR-error message-03 writefileview.py # 2016-02-22 23:04:15,017-TEST-LOG-CRITICAL-critical message-03 writefileview.py
shutil
高级的 文件、文件夹、压缩包 处理模块
1、文件、文件夹拷贝移动删除
__author__ = 'Administrator' #-*- coding:utf-8 -*- # shutil # 高级的 文件、文件夹、压缩包 处理模块 import shutil print(dir(shutil)) ['Error', 'ExecError', 'ReadError', 'RegistryError', 'SameFileError', 'SpecialFileError', '_ARCHIVE_FORMATS', '_BZ2_SUPPORTED', '_LZMA_SUPPORTED', '_UNPACK_FORMATS', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_basename', '_check_unpack_options', '_copyxattr', '_destinsrc', '_ensure_directory', '_find_unpack_format', '_get_gid', '_get_uid', '_make_tarball', '_make_zipfile', '_ntuple_diskusage', '_rmtree_safe_fd', '_rmtree_unsafe', '_samefile', '_unpack_tarfile', '_unpack_zipfile', '_use_fd_functions', 'chown', 'collections', 'copy', 'copy2', 'copyfile', 'copyfileobj', 'copymode', 'copystat', 'copytree', 'disk_usage', 'errno', 'fnmatch', 'get_archive_formats', 'get_terminal_size', 'get_unpack_formats', 'getgrnam', 'getpwnam', 'ignore_patterns', 'make_archive', 'move', 'nt', 'os', 'register_archive_format', 'register_unpack_format', 'rmtree', 'stat', 'sys', 'tarfile', 'unpack_archive', 'unregister_archive_format', 'unregister_unpack_format', 'which'] # http://blog.sina.com.cn/s/blog_818b48820101odb2.html #应用场景:文件本身、文件内容、文件夹的的拷贝可以用于备份 #1拷贝文件内容(部分或者全部) # shutil.copyfileobj(fsrc, fdst[, length]) # 将文件内容拷贝到另一个文件中,可以部分内容 with open("001.txt", 'rb') as fsrc: #第一个文件对象读出 with open("002.txt", 'wb') as fdst: #第二个文件对象写入 shutil.copyfileobj(fsrc, fdst) #fsrc和fdst都是文件对象,最后实现的是文件001.txt中的内容全部拷贝到了文件002.txt中 #2shutil.copyfile(src, dst) #这里src值的是文件名字,不带路径指的是当前路径,也可以通过绝对路径拷贝到别的目录下 # 拷贝文件(把当前目录下的文件"001.txt"拷贝到当前目录下,重命名为"003.txt",001和003 2个文件的内容一样) # shutil.copyfile("001.txt", "003.txt") #当前目录下 # shutil.copyfile("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\001.txt", # "D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\001\\002.txt") #绝对路径的文件拷贝 #文件拷贝可以多次拷贝,后面的文件覆盖之前的文件,不会提示文件已经存在,不能覆盖(和文件夹拷贝不一样) #3 递归拷贝文件夹(将文件夹001下的所有子文件夹子文件全部拷贝到文件夹002下) # shutil.copyfile("001", "003") #这里文件夹必须要用绝对路径,用相对路径或者直接用文件名,会报错 # PermissionError: [Errno 13] Permission denied: '001' # shutil.copytree("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\001", # "D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\003") # 执行后会在001文件夹下多出一个002文件夹,并且002文件夹下有001文件夹下的所有内容. # 多次拷贝文件夹,文件存在,不能被覆盖,会报错,FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。 #二、移动-重命名 # shutil.move(src, dst) # 递归的去移动文件 # shutil.move("001", "002\\001") #可以用相对路径移动(剪切)--反斜杠转义\\ # # 执行后会把001文件夹移动到002\\001文件夹下面 # shutil.move("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\002", # "D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\003\\") ## 执行后会把002文件夹移动剪切到003文件夹下,注意003后面有\\ # shutil.move("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\003", # "D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\004") ## 执行后会把003文件夹重命名成004--当前路径就是重命名,不同的路径就是移动剪切,注意004后面没有\\ #三、删除 # shutil.rmtree(path[, ignore_errors[, onerror]]) # 递归的去删除文件 # shutil.rmtree("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\003") #绝对路径的方式删除文件夹003 # shutil.rmtree("003") ##相对路径(当前目录下)的方式删除文件夹003 # 可以发现003文件夹连同下面的文件都消失了。
2、文件、文件夹打包压缩解压
__author__ = 'Administrator' #-*- coding:utf-8 -*- import shutil import zipfile import tarfile #一、压缩解压 应用场景:备份就涉及到压缩 #1 打包压缩 #1.1 放在当前目录 # 将 D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\004 下的文件打包放置当前程序目录 # shutil.make_archive("wwww", 'gztar', root_dir='D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\004') #绝对路径 # shutil.make_archive("wwww", 'gztar', root_dir='004') #相对路径:打包后的文件名字wwww.tar.gz #参数1:文件名 参数2:压缩格式 参数3:待压缩文件路径 # def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, # dry_run=0, owner=None, group=None, logger=None): #1.2 放在指定目录 #将 当前目录下004 下的文件打包放置在目录:"D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\005\\wwww" # shutil.make_archive("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\005\\wwww", 'gztar', root_dir='004') # format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar” # root_dir: 要压缩的文件夹路径(默认当前目录) # shutil.make_archive(base_name, format,...)# # 创建压缩包并返回文件路径,例如:zip、tar# # base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径, # 如:www =>保存至当前路径 # 如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ # format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar” # root_dir: 要压缩的文件夹路径(默认当前目录) # owner: 用户,默认当前用户 # group: 组,默认当前组 # logger: 用于记录日志,通常是logging.Logger对象 # shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细: #二、压缩-zipfile # z=zipfile.ZipFile("zip1.zip","w") # z.write("001.txt") # z.write("002.txt") # z.close() #解压-zipfile # z=zipfile.ZipFile("zip1.zip","r") # z.extractall() # z.close() #三、tarfile压缩解压 #1压缩 # tar1 = tarfile.open("your.tar","w") #新建一个空白的tar压缩包 模式是w # # tar1.add("D:\\PycharmProjects\\s12\\day6_0220\\03 xiaojie\\06 shutil模块\\005") #绝对路径也可以 # tar1.add("004") #把当前路径下的004文件夹添加到压缩包 # tar1.add("005") #把当前路径下的005文件夹添加到压缩包 # tar1.close() #2解压 # tar2 = tarfile.open("your.tar","r") # tar2.extractall() ## 可设置解压地址 默认是解压当当前路径 # tar2.close() tar2 = tarfile.open("your.tar","r") tar2.extractall("001\\") # 可设置解压地址 默认是解压当当前路径 这里是解压的当前路径下001文件夹下 tar2.close()
面向对象
1、为什么要用面向对象?函数式编程的短板
__author__ = 'Administrator' #-*- coding:utf-8 -*- #1定义角色--字典的形式定义每个角色的属性:姓名、角色、武器、生命值、钱数 2个角色 4个人(2警察 2 土匪) roles = { 1:{'name':'Alex', 'role':'terrorist', #恐怖分子 'weapon':'AK47', 'life_value': 100, 'money': 15000, }, 2:{'name':'Jack', 'role':'police', 'weapon':'B22', 'life_value': 100, 'money': 15000, }, 3:{'name':'Rain', 'role':'terrorist', 'weapon':'C33', 'life_value': 100, 'money': 15000, }, 4:{'name':'Eirc', 'role':'police', 'weapon':'B51', 'life_value': 100, 'money': 15000, }, } #取出字典中每个角色的属性 print(roles[1]) #{'name': 'Alex', 'money': 15000, 'life_value': 100, 'role': 'terrorist', 'weapon': 'AK47'} print(roles[1]["name"]) #Alex print(roles[2]) #{'name': 'Jack', 'money': 15000, 'life_value': 100, 'role': 'police', 'weapon': 'B22'} print(roles[2]["name"]) #Jack #2定义函数:开枪、中枪、买枪 def shot(by_who): #开枪 pass #开了枪,子弹数减少 def got_shot(who): who["life_value"] -=10 #血小于0,就死了,游戏结束(格斗) pass #中枪后减血,这个减少的血可以固定也可以random随机 #判断防弹衣,伤害减少 def buy_gun(who,gun_name): pass #买了枪要扣钱,判断钱够不够 # 函数式编程需要改进的地方: # 1、1、没有做权限的设置,恐怖分子也可以调保护人质的函数,这个不对;恐怖分子和警察调的函数是不一样的 # 我们是没办法 把这2个角色适用的功能区分开来的,也就是说,每个角色都可以直接调用任意功能,没有任何限制。 # ----oop中设置3个类来解决(警察类、土匪类、公共类) # 2、每个角色定义的属性名称是一样的,但这种命名规则是我们自己约定的,从程序上来讲,并没有进行属性合法性检测, # 也就是说role 1定义的代表武器的属性是weapon, role 2 ,3,4也是一样的, # 不过如果我在新增一个角色时不小心把weapon 写成了wepon , 这个程序本身是检测 不到的,属性写了多套,有重复代码 # 3、现在需要给所有角色添加一个可以穿防弹衣的功能,那很显然你得在每个角色里放一个属性来存储此角色是否穿 了防弹衣,那就要更改每个角色的代码, # 给添加一个新属性,这样太low了,不符合代码可复用的原则,不方便扩展 # -----直接在oop中加一个属性解决 # 4、 但其实我不通过got_shot(),直接调用角色roles[role_id][‘life_value’] 减血也可以呀,但是如果这样调用的话,那可以就是简单粗暴啦 # 因此这里应该设计 成除了通过got_shot(),其它的方式是没有办法给角色减血的,不过在上面的程序设计里,是没有办法实现的。 # ----在oop中定义生命属性为私有的,只能通过调用got_shot()方法,才能修改 # OOP编程的主要作用也是使你的代码修改和扩展变的更容易,更好的避免重复代码
2、类、实例、初始化方法、封装介绍
__author__ = 'Administrator' #-*- coding:utf-8 -*- #类名字的首字母最好大写(编码规范) class Role(object): #定义新式类 定义一个类, class是定义类的语法,Role是类名,(object)是新式类的写法 def __init__(self,name,role,weapon,life_value=100,money=15000): #初始化方法(构造方法),实例化的时候默认调用 #初始化方法,在生成一个角色时要初始化的一些属性就填写在这里 self.name = name #把24行实例r1的实际参数"jack"通过形参name传递给r1.name self.role = role self.weapon = weapon self.life_value = life_value self.money = money def shot(self): #方法(实例r1调用这个方法,self就是实例本身r1;实例r2调用这个方法,self就是实例本身r2) print("shooting...") def got_shot(self): print("I got shot...") def buy_gun(self,gun_name): print("%s just bought %s" % (self.name,gun_name)) r1 = Role("jack","police","B22") #创建实例-实例化--这里实例化可以带参数也可以不带参数,带参数的是初始化属性的字段 # 格式 实例名=类名([参数可选]) r2 = Role("tom","terrorist","Ak47") #相当于Role(r1,'Alex','police','AK47’) 此时self 相当于 r2 , #1\在内存中开辟一块空间指向r1这个变量名 # 相比函数式写法,上面用面向对象中的类来写最直接的改进有以下2点: # 代码量少了近一半 # 角色和它所具有的功能可以一目了然看出来 # r1 = Role('Alex','police','AK47') # r1.buy_gun("B21”) #python 会自动帮你转成 Role.buy_gun(r1,”B21") # 执行结果 # #Alex has just bought B21 #调用类中的一个方法时,你得告诉人家你是谁。 # 总结一下2点: # 1、上面的这个r1 = Role('Alex','police','AK47’)动作,叫做类的“实例化”, # 就是把一个虚拟的抽象的类,通过这个动作,变成了一个具体的对象了, 这个对象就叫做实例 # 2、刚才定义的这个类体现了面向对象的第一个基本特性, # 封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容 # 4、面向对象-cs # 1、定义3个类:--区分不同角色可以干不同的事情,权限控制--ok # 1、警察类:只存放警察特有的方法:保护人质、拆炸药(警察类继承公共类men) # 2、土匪类:只存放土匪特有的方法:杀害人质、装炸药(土匪类继承公共类men) # 3、警察和土匪公用的类--men:买枪、开枪、中枪掉血等方法 # 封装 # 封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。 # 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 # # 继承--减少重复代码 # 面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 # 继承的过程,就是从一般到特殊的过程。 # 实现继承是指使用基类的属性和方法而无需额外编码的能力; # 在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。 # 例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。 # 但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。(腿可以直接放在类的属性中) # 父类仅定义将由子类创建的一般属性和方法。 # # OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。 # cs:划分对象:不同的人(人公共类、警察类、土匪类、人质类),不同的枪,不同的场景 --3个不同的大类
3、类变量、实例变量、继承
__author__ = 'Administrator' #-*- coding:utf-8 -*- class SchoolMember(object): members = 0 #初始学校的人数是0 类变量(类属性) def __init__(self,name,age): #初始化方法,定义name,age self.name = name self.age = age def tell(self): pass #自我介绍 def enroll(self): #注册 SchoolMember.members += 1 #类变量+1 print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " %(self.name,SchoolMember.members)) def __del__(self): # '''析构方法''' (老师跳槽、学生退学等) print("\033[31;1mmember [%s] is leaved!\033[0m" %self.name) class Teacher(SchoolMember): def __init__(self,name,age,course,salary): #重写初始化方法 super(Teacher,self).__init__(name,age) #继承父类的属性name,age(不必单独再初始化这个2个属性了) self.course = course self.salary = salary self.enroll() #调父类的注册方法,人数+1(每新建一个老师,学校人数加1) def teaching(self):#哪个老师讲哪门课,给哪个班级 print("Teacher [%s] is teaching [%s] for class [%s]" %(self.name,self.course,"s12")) def tell(self): #自我介绍方法重写(对于父类) print("hi,my name is [%s],works for [%s] as a [%s] teacher" % (self.name,"oldboy",self.course)) class Student(SchoolMember): def __init__(self,name,age,grade,sid):#重写父类初始化方法 super(Student,self).__init__(name,age) #继承父类的属性name,age(不必单独再初始化这个2个属性了) # super(Student,self) 这里是逗号,不是点 self.grade = grade #班级 self.sid = sid #学号 self.enroll() #调父类的注册方法,人数+1(每新建一个学生,学校人数加1) def tell(self): #对父类自我介绍方法重写 print("Hi,my name is [%s], i am study in [%s] in [%s]" %(self.name,self.grade,"oldboy")) if __name__ == "__main__": #这里main2边是__ t1 = Teacher("alex","21","python",3000) t2 = Teacher("wusir","23","python",3001) s1 = Student("sanjiang","18","s12","001") s2 = Student("qinghua","17","s12","002") # t1.teaching() # t2.tell() # s1.tell() s2.tell() #通过实例调方法 #1 输出初始化方法中的方法--注册方法 #2 输出方法本身--自我介绍 #3 输出父类的析构方法

浙公网安备 33010602011771号