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的文件添加新的节点?
View Code

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文件没有缩进?需要手动调整,怎么在文件中自动缩进换行?
View Code

 

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)
View Code

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
View Code

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")) #重新写入到文件,文件内容进行了修改
View Code

 

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位
View Code

应用场景:微信登录,后台密码是用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-
View Code

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
View Code

 

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文件夹连同下面的文件都消失了。
View Code

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()
View Code

 

面向对象

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编程的主要作用也是使你的代码修改和扩展变的更容易,更好的避免重复代码
View Code

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个不同的大类
View Code

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 输出父类的析构方法
View Code

 

posted @ 2016-02-23 17:31  王同佩  阅读(164)  评论(0)    收藏  举报