Python开发【第六篇】:面向对象
configparser模块
configparser用于处理特定格式的文件,其本质是利用open来操作文件。
文件a.txt
- [section1]
- k1 = 123
- k2:v2
- [section2]
- k1 = 234
加载文件a.txt
- import configparser
- config = configparser.ConfigParser()
- config.read('a.txt',encoding='utf-8')
对文件相关操作
- import configparser
- config = configparser.ConfigParser()
- config.read('a.txt',encoding='utf-8')
- #获取所有节点
- ret = config.sections()
- print(ret)
- #获取指定节点下的所有键值对
- ret = config.items('section1')
- print(ret)
- #获取指定节点下所有的键
- ret = config.options('section1')
- print(ret)
- #获取指定节点下指定key的值
- ret = config.get('section1','k1')
- #转换成int
- # ret = config.getint('section1','k1')
- #转换成float
- # ret = config.getfloat('section1','k1')
- #转换成boolean
- # ret = config.getboolean('section1','k1')
- print(ret)
- #检查、删除、设置指定组内的键值对
- #检查
- has_opt = config.has_option('section1')
- print(has_opt)
- #添加节点
- config.add_section('SEC_1')
- config.write(open('a.txt','w'))
- #删除节点
- config.remove_section('SEC_1')
- config.write(open('a.txt','w'))
- #检查、删除、设置指定组内的键值对
- #检查
- has_opt = config.has_option('section1','k1')
- print(has_opt)
- #删除
- config.remove_option('section1','k1')
- config.write(open('a.txt','w'))
- #设置
- config.set('section1','k10','123')
- config.write(open('a.txt','w'))
XML模块
xml是实现不同语言或程序之间进行数据交换的协议。
文件xml_text.xml
- <data>
- <country name="Liechtenstenin">
- <rank update="yes">2</rank>
- <year>2023</year>
- <gdppc>141100</gbppc>
- <neighbor direction="E" name="Austria"/>
- <neighbor direction="W" name="Switzerland"/>
- </country>
- <country name="Sinagapore">
- <rank update="yes">5</rank>
- <year>2026</year>
- <gdppc>59900</gdppc>
- <neighbor direction="N" name="Malaysia"/>
- </country>
- <country name="Panama">
- <rank update="yes">69</rank>
- <year>2026</year>
- <gdppc>13600</gdppc>
- <neighbor direction="W" name="Costa Rica"/>
- <neighbor direction="E" name="Costa Rica"/>
- </country>
- </data>
xml相关操作
解析xml文件
- from xml.etree import ElementTree as ET
- #直接解析xml文件
- tree = ET.parse('xml_test.xml')
- #获取xml文件的根节点
- root = tree.getroot()
- print(root)
- print(root.tag)
- print(root.attrib)
- """
- 输出:
- <Element 'data' at 0x00000000006D0688>
- data
- {'title_2': 'test_2', 'title_1': 'test_1'}
- """
解析字符串
- from xml.etree import ElementTree as ET
- #打开文件,读取xml内容
- str_xml = open('xm_test.xml','r').read()
- #将字符串解析成xml特殊对象,root代指xml文件的根节点
- root = ET.XML(str_xml)
遍历xml文档的所有内容
- from xml.etree import ElementTree as ET
- #直接解析xml文件
- tree = ET.parse('xml_test.xml')
- #获取xml文件的根节点
- root = tree.getroot()
- #遍历xml文档的第二层
- for child in root:
- #第二层节点的标签名称和标签属性
- print(child.tag,child.attrib)
- #遍历xml文档的第三层
- for i in child:
- #第三层节点的标签名称和内容
- print(i.tag,i.text)
- """
- 输出:
- country {'name': 'Liechtenstenin'}
- rank 2
- year 2023
- gdppc 141100
- neighbor None
- neighbor None
- country {'name': 'Sinagapore'}
- rank 5
- year 2026
- gdppc 59900
- neighbor None
- country {'name': 'Panama'}
- rank 69
- year 2026
- gdppc 13600
- neighbor None
- neighbor None
- """
修改xml
解析字符串方式进行修改
- from xml.etree import ElementTree as ET
- str_xml = open('xml_test.xml','r').read()
- root = ET.XML(str_xml)
- #获取顶层标签
- print(root.tag)
- #循环所有的year节点
- for node in root.iter('year'):
- #将year节点中的内容自增一
- new_year = int(node.text) + 1
- node.text = str(new_year)
- #设置属性
- node.set('name','alex')
- node.set('age','19')
- #删除属性
- del node.attrib['name']
- #更新文件
- tree = ET.ElementTree(root)
- tree.write("new_xml_test.xml",encoding='utf-8')
解析文件方式进行修改
直接调用tree.write写入即可。
- from xml.etree import ElementTree as ET
- tree = ET.parse('xml_test.xml')
- root = tree.getroot()
- """
- 操作
- """
- #更新文件
- tree.write("new_xml_test2.xml",encoding='utf-8')
添加节点
- from xml.etree import ElementTree as ET
- tree = ET.parse('xml_test.xml')
- root = tree.getroot()
- ele = ET.Element('Alex',{'k1':'v1'})
- ele.text = "test"
- root.append(ele)
- tree.write("new.xml",encoding='utf-8')
结果new.xml:
- <data title_1="test_1" title_2="test_2">
- """
- 原内容
- """
- <Alex k1="v1">test</Alex></data>
由于原生保存xml时默认无缩进,如果要设置缩进需要修改保存方式。
- from xml.etree import ElementTree as ET
- from xml.dom import minidom
- def prettify(elem):
- """
- 将节点转换成字符串,并添加缩进
- :param elem:
- :return:
- """
- rough_string = ET.tostring(elem,'utf-8')
- reparsed = minidom.parseString(rough_string)
- return reparsed.toprettyxml(indent="\t")
- #创建根节点
- root = ET.Element("family")
- #创建大儿子
- # son1 = ET.Element('son',{'name':'儿1'})
- son1 = root.makeelement('son',{'name':'儿1'})
- #创建小儿子
- # son2 = ET.Element('son',{'name':'儿2'})
- son2 = root.makeelement('son',{'name':'儿2'})
- #在儿子中创建2个孙子
- # grandson1 = ET.Element('grandson',{'name':'儿11'})
- grandson1 = root.makeelement('grandson',{'name':'儿11'})
- # grandson2 = ET.Element('grandon',{'name':'儿12'})
- grandson2 = root.makeelement('grandon',{'name':'儿12'})
- son1.append(grandson1)
- son2.append(grandson2)
- #把儿子添加到根节点
- root.append(son1)
- root.append(son2)
- raw_str = prettify(root)
- f = open('family.xml','w',encoding='utf-8')
- f.write(raw_str)
- f.close()
family.xml:
- <?xml version="1.0" ?>
- <family>
- <son name="儿1">
- <grandson name="儿11"/>
- </son>
- <son name="儿2">
- <grandon name="儿12"/>
- </son>
- </family>
shutil
高级的文件、文件夹、压缩包处理模块。
shutil.copyfileobj(ferc,fdst[,length])
将文件内容拷贝到另一个文件中
- import shutil
- shutil.copyfileobj(open('old.xml','r'),open('new.xml','w'))
shuit.copyfile(src,dst)
拷贝文件
- shutil.copyfile('f1.log','f2.log')
zipfile、tarfile
zipfile创建压缩包
- import zipfile
- #压缩
- z = zipfile.ZipFile('test.zip','a')
- z.write('new.xml')
- z.write('family.xml')
- z.close
zipfile解压压缩包
- #解压
- z = zipfile.ZipFile('test.zip','r')
- #解压全部
- # z.extractall()
- #解压单个文件
- z.extract("new.xml")
- #获取压缩包的成员
- for item in z.namelist():
- print(item)
- z.close()
tarfile创建压缩包
- import tarfile
- #压缩
- tar = tarfile.open("test.tar",'w')
- #arcname重命名
- tar.add('test.py',arcname='test_1.py')
- tar.add('xml_test.py',arcname='xml_test.py')
- tar.close()
tarfile解压压缩包
- tar = tarfile.open('test.tar','r')
- #可设置解压路径
- # tar.extractall()
- for item in tar.getmembers():
- print(item,type(item))
- obj = tar.getmember("test_1.py")
- print(obj,type(obj))
- tar.extract(obj)
- tar.close()
系统命令
call
获取状态码,0正常。
- import subprocess
- #shell=False命令传入方式为列表
- ret = subprocess.call(["ls","-l"],shell=False)
- #shell=True命令传入方式为字符串
- ret = subprocess.call("ls -l",shell=True)
check_call
执行命令,如果执行状态码是0,则返回0,否则抛出异常。
- ret = subprocess.check_call("ls -l",shell=True)
check_output
执行命令,如果状态码是0,则返回执行结果,否则抛出异常。
- ret = subprocess.check_output("ls -l",shell=True)
函数式编程和面向对象编程实现发送邮件功能。
函数实现:
- def mail(email,message):
- print("发送")
- return True
- mail("xxxx.@126.com","hello")
面向对象实现:
- class Foo:
- #方法
- def mail(self,email,message):
- print("发送")
- return True
- #调用
- #1、创建对象,类名()
- obj = Foo()
- #2、通过对象去执行方法
- obj.mail("xxxx.@126.com","hello")
类和对象
1、创建类:
class 类名:
def 方法名(self,xxx):
pass
2、创建对象
对象 = 类名()
3、通过对象执行方法
对象.方法名(xxx)
函数式
def fetch(host,username,passwd,sql):
pass
def create(host,username,passwd,sql):
pass
def remove(host,username,passwd,sql):
pass
def modify(host,username,passwd,sql):
pass
fetch(…)
面向对象:
class SQLHelper:
def fetch(self,host,username,passwd,sql):
pass
def create(self,host,username,passwd,sql):
pass
def remove(self,host,username,passwd,nid):
pass
def modify(self,host,username,passwd,name):
pass
obj = SQLHelper()
obj.fetch(…)
面向对象优化:
class SQLHelper:
def fetch(self, sql):
pass
def create(self,sql):
pass
def remove(self,nid):
pass
def modify(self,name):
pass
obj = SQLHelper()
obj.hhost = "xxx.xxx.xxx"
obj.uusername = "xxxx"
obj.passwd = "xxxx"
obj.fetch("sql")
- class SQLHelper:
- def fetch(self, sql):
- #链接数据库
- print(self.hhost)
- print(self.uusername)
- print(self.passwd)
- print(sql)
- def create(self,sql):
- pass
- def remove(self,nid):
- pass
- def modify(self,name):
- pass
- obj = SQLHelper()
- obj.hhost = "xxx.xxx.xxx"
- obj.uusername = "xxxx"
- obj.passwd = "xxxx"
- obj.fetch("select * from A")
- 输出:
- xxx.xxx.xxx
- xxxx
- xxxx
- select * from A
什么时候使用面向对象?
当某些函数具有相同参数时,可以使用面向对象的方式,将参数值一次性封装到对象中,方便以后去对象中取值。
self是什么?
self是一个python自动传值的参数,那个对象执行方法,self就是谁。
obj1 = SQLHelper()
obj1.hhost = "1xxx.xxx.xxx"
obj1.uusername = "xxxx"
obj1.passwd = "xxxx"
obj1.fetch("sql") #self==obj1
obj2 = SQLHelper()
obj2.hhost = "2xxx.xxx.xxx"
obj2.uusername = "xxxx"
obj2.passwd = "xxxx"
obj2.fetch("sql") #self==obj2
构造方法
类中有一个特殊的方法__init__,类()自动被执行。
- class SQLHelper:
- def __init__(self,a1,a2,a3):
- self.hhost = a1
- self.uusername = a2
- self.passwd = a3
- print("自动执行init")
- def fetch(self, sql):
- #链接数据库
- print(self.hhost)
- print(self.uusername)
- print(self.passwd)
- print(sql)
- def create(self,sql):
- pass
- def remove(self,nid):
- pass
- def modify(self,name):
- pass
- obj1 = SQLHelper("1xxx.xxx.xxx","xxxx","xxxx")
- obj1.fetch("select * from A")
- obj2 = SQLHelper("2xxx.xxx.xxx","xxxx","xxxx")
- obj2.fetch("select * form A")
- 输出:
- 自动执行init
- 1xxx.xxx.xxx
- xxxx
- xxxx
- select * from A
- 自动执行init
- 2xxx.xxx.xxx
- xxxx
- xxxx
- select * form A
面向对象三大特性:封装、继承、多态。
封装
面向对象的程序设计中,某个类把所需要的数据(类的属性)和对数据的操作(类的行为)全部都封装在类中,分别称为类的成员变量和方法(成员函数)。这种把成员变量和成员函数封装在一起的编程特性称为封装。
- class c1:
- def __init__(self,name,obj):
- self.name = name
- self.obj = obj
- class c2:
- def __init__(self,name,age):
- self.name = name
- self.age = age
- def show(self):
- print(self.name)
- class c3:
- def __init__(self,a1):
- self.money = 123
- self.aaa = a1
- c2_obj = c2('aa',11)
- c1_obj = c1("alex",c2_obj)
- print(c1_obj.obj.age)
- c3_obj = c3(c1_obj)
- print(c3_obj.aaa.obj.age)
- 输出:
- 11
- 11
继承
继承是两个类或多个类之间的父子关系,子进程继承父进程的所有公有实例变量和方法。继承实现了代码的重用。重用已经存在的数据和行为,减少代码的重新编写,python在类名后用一对圆括号表示继承关系,括号中的类表示父类,如果父类定义了__init__方法,则子类必须显示地调用父类的__init__方法,如果子类需要扩展父类的行为,可以添加__init__方法的参数。
单继承
- class F1:#父类、基类
- def show(self):
- print('show')
- #F2继承F1
- class F2(F1):#子类、派生类
- def bar(self):
- print('bar')
- obj = F2()
- obj.bar()
- obj.show()
- 输出:
- bar
- show
- class F1:#父类、基类
- def show(self):
- print('show')
- def foo(self):
- print(self.name)
- #F2继承F1
- class F2(F1):#子类、派生类
- def __init__(self,name):
- self.name = name
- def bar(self):
- print('bar')
- def show(self):#自己的优先级更高
- print('F2 show')
- obj = F2('alex')
- obj.bar()
- obj.show()
- obj.foo()
- 输出:
- bar
- F2 show
- alex
- class S1:
- def F1(self):
- self.F2()
- def F2(self):
- print('S1.F2()')
- class S2(S1):
- def F3(self):
- self.F1()
- def F2(self):
- print('S2.F2()')
- obj = S2()
- obj.F3()
- 输出:
- S2.F2()
多继承
- class C1:
- def f1(self):
- pass
- class C2:
- def f2(self):
- pass
- class C3(C2,C1):
- pass
- obj = C3()
- class C1:
- def f1(self):
- print("C1.f1()")
- class C2:
- def f1(self):
- print("C2.f1()")
- class C3(C2,C1):
- pass
- obj = C3()
- obj.f1()
- 输出:
- C2.f1()
- class C0:
- def f1(self):
- print("C0.f1()")
- class C1():
- def f1(self):
- print("C1.f1()")
- class C2(C0):
- def f2(self):
- print("C2.f1()")
- class C3(C2,C1):
- pass
- obj = C3()
- obj.f1()
- 输出:
- C0.f1()
- class C_2:
- def f1(self):
- print("C_2.f1()")
- class C_1(C_2):
- def f1(self):
- print("C_1.f1()")
- class C0(C_2):
- def f2(self):
- print("C0.f1()")
- class C1(C_1):
- def f1(self):
- print("C1.f1()")
- class C2(C0):
- def f2(self):
- print("C2.f1()")
- class C3(C2,C1):
- pass
- obj = C3()
- obj.f1()
- 输出:
- C1.f1()
继承总结
对于继承其方法(属性)可能定义在当前类,也可能来自于基类,所以在方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。而搜索的顺序就是所谓的方法解析顺序(MRO、Method Resolution Order)。对于单继承来说,MRO一般比较简单,而对于多继承来说,MRO比较复杂。下面就二种基本的继承模式解析。
posted on 2017-01-20 17:48 yinshoucheng 阅读(510) 评论(0) 编辑 收藏 举报