oop、configparser、xml模块

时间:2024-04-18 21:07:43
本节大纲:
oop、configparser、xml模块
一:在python中,有两种编程思想。1:函数式编程。2:oop。无论是函数式编程还是oop都是相辅相成。并不是说oop比函数式编程就好。各有各的优缺点。
在其他语言中java等只能以面向对象进行编程。
函数放在类中叫做方法。
只有对象才能调用类中的方法,也就是说需要创建该类的对象然后调用该类的方法。
而函数调用直接进行调用。

oop、configparser、xml模块

类需要创建对象,通过对象调用执行类中的方法。而函数可以直接进行调用,无需创建对象。

1:创建对象:和函数式调用雷同:类名()

obj=coo()

2:通过对象执行类中的方法.对象和属性用圆句点(.)进行连接。

obj.co()

二:定义类的语法:

a:class  类名:

def 方法名(self,x)

passs

关键字:class ,然后跟着类名。任何函数在类中都叫方法。方法的第一个参数必须是self。在构造对象的时候,会自动把对象名字传给self。类中的方法只能是对象来调用。

b:对象创建:

对象名=类名()

c:通过对象来执行类中的方法。

三:类和对象的关系

oop、configparser、xml模块

在创建对象的时候,在对象的内部有一个类对象指针指向自己的类。当对象执行check()方法的时候,根据类指针找到自己的类sql中的方法check进行执行。并把对象obj当做实参传给方法check的self形参。

并不是对象有该方法。

四:在什么情况下使用面向对象?

需求:对数据库的增删改查操作

a:函数式编程

 #!/usr/bin/env python
def check(host,user,pwd,sql):
pass
def add(host,user,pwd,sql):
pass
def delete(host,user,pwd,sql):
pass
def update(host,user,pwd,sql):
pass
check('1.1.1.1','evil','','....')
add('1.1.1.1','evil','','....')
delete('1.1.1.1','evil','','....')
update('1.1.1.1','evil','','....')

没调用都需要传入,host、user、pwd、sql参数。如果操作数据库的动作较多,会反复传入多次。

面向对象编程:

 class sql:
def check(self,sql):
print(self.host)
print(self.user)
print(self.password)
def crate(self,sql):
pass
def update(self,sql):
pass
def delete(self,sql):
pass obj=sql()
obj.host='1,1,1,1'
obj.user='evil'
obj.password=''
obj.check("select * from A")
,,,
evil

当我们执行相关操作的时候,我们只需要把数据封装到对象里,在调用类的方法的时候,自动获取对象的属性值,即可连接到数据库。而不需要每次都需要把账号、主机、密码都传入方法中进行操作。

什么时候用面向对象呢?

当某一些函数中有相同的参数的时候,可以用面向对象的封装特性,将参数值一次性的封装到对象,之后执行该对象的类的方法的时候不需要每次传入对应的参数。每次执行类的方法的时候,只需要从对象中取值即可。

五:self参数。

self 是python自动传值的形式参数。

当对象调用类的方法的时候,会自动把对象的赋值给self形式参数。

oop、configparser、xml模块

当obj调用类的方法check时候,self会自动赋值为obj,当obj1调用类sql的方法check时候,self会自动赋值obj1。

也就是说可以通过创建不通的对象来实现连接不通的数据库。

六:构造方法__init__

当执行类名()时候会自动执行类中的方法:__init__方法。

 class sql:
def __init__(self):
print('__init__')
def check(self,sql):
print(self.host)
print(self.user)
print(self.password)
def crate(self,sql):
pass
def update(self,sql):
pass
def delete(self,sql):
pass obj=sql()
__init__

也就是说当执行对象创建的时候,也就是执行sql()的时候,会自动执行__init__方法。

根据这个特性,我们以后将对象封装的数据,方法__init__方法中。

 class sql:
def __init__(self,a,b,c):
self.host=a
self.user=b
self.password=c
def check(self,sql):
print(self.host)
print(self.user)
print(self.password)
def crate(self,sql):
pass
def update(self,sql):
pass
def delete(self,sql):
pass obj=sql('1.1.1.1','evil','')
obj.check('selec.....') 1.1.1.1
evil

通过对象创建的时候,对__init__方法的参数进行实参的传入。

__init__方法叫做构造方法。构造对象的方法。

七:调用顺序

函数调用的时候,需要先声明函数,才能进行调用,而在类中,没有这个上下顺序,可以在方法声明前进行调用。

 class sql:
def __init__(self,a,b,c,d):
self.host=a
self.user=b
self.password=c
self.check(d)
def check(self,sql):
print(self.host)
print(self.user)
print(self.password)
print(sql)
def crate(self,sql):
pass
def update(self,sql):
pass
def delete(self,sql):
pass obj=sql('1.1.1.1','evil','','check')
1.1.1.1
evil check

其中self.check(d)相当于obj.check('check')只不过是在构造方法执行的时候调用这个函数。

八:封装

 class game_life:
def __init__(self,name,age,fight):
self.name=name
self.age=age
self.fight=fight
def battle_row(self):
self.fight=self.fight-
def study(self):
self.fight=self.fight+
def person_game(self):
self.fight=self.fight- obj=game_life('苍井井','',)
obj.battle_row()
print(obj.fight)

也就说 可以通过类的方法对类的对象的值进行修改。

面向对象三大特性:封装、继承、多太。

封装:将数据通过__init__方法封装到对象中。供方法进行调用和操作。

九:封装的对象可以数据,也可以是对象,可以任意东西。

 class a:
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(self.name)
class b:
def __init__(self,name,obj):
self.name=name
self.obj=obj obj_a=a('evil',)
obj_b=b('tom',obj_a)
print(obj_b.obj.name)
print(obj_b.obj.age)
evil

oop、configparser、xml模块

也就是对象ojb封装的是name和对象obj_a.也就是说封装可以是数据,也可以是对象,也可以是任意事物。

 class a:
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(self.name)
class b:
def __init__(self,name,obj):
self.name=name
self.obj=obj
class c:
def __init__(self,name,a):
self.name=name
self.a=a obj_a=a('evil',)
obj_b=b('tom',obj_a)
obj_c=c('jack',obj_b)
print(obj_c.a.obj.name)
obj_c.a.obj.show() evil
evil
res=obj_c.a.obj.show()
print(res)

注意show方法没有返回值,所以res值是None.

oop、configparser、xml模块

也就是通过obj_c怎么访问obj_a.show()或者obj_a.name?

如上图所示obj_c.a是obj_b对象,而obj_b.obj对象是obj_a对象,obj_a.name  obj_a.show()是我们想要的结果。

所以:obj_c.a.obj.name   obj_c.a.obj.show()

十:继承

在其他语言里java里只有单继承,而在python 中可以有多继承。语法:

 class a:
def show(self):
print('show')
class b(a):
def co(self):
print('co')
obj=b()
obj.show()
show

也就是在类名后面加个(继承类的类名)即可。也就是说a相当于与b是父类,b相对于a是子类,或者说a是基类,b是派生类。注意说法,各自对应。谁是父类,谁是子类只是相对而言。子类可以继承父类的方法。父类不可以继承子类的方法。

如上,当对象obj调用方法show的时候,优先看自己类中是否有该方法,如果有就执行,不去父类找该方法。如果该方法没有的话去找他的父类是否有该方法。如果有就执行。

 class a:
def show(self):
print('show')
class b(a):
def co(self):
print('co')
def show(self):
print('b')
obj=b()
obj.show()
b

继承的本质:子类没有的方法,方法在父类里,在对象调用该方法的时候,相当于父类的方法拿到子类的中。如下:

 class a:
def __init__(self,name):
self.name=name
def show(self):
print(self.name)
class b(a):
def __init__(self,name):
self.name=name
def co(self):
print('co')
obj=b('tom')
obj1=a('evil')
obj.show()
tom

也就是说子类对象obj在调用父类show方法的时候,传入的self.name是子类的self.name。也就是说相当于把父类的方法show拿到子类中。

oop、configparser、xml模块

如上所示:对象obj在执行方法show时候优先去子类b中找show方法,如果子类没有show方法的话,去父类的a中找show方法,并执行show方法,show方法

相当于拿到子类b中,因为子类b在构造对象obj的时候,已经封装数据self.name=name,所以获取的是子类的b的对象数据,也就是tom。而不是父类a的self.name属性。

 class a:
def s1(self):
print(a)
def s2(self):
self.s1()
class b(a):
def s1(self):
print('b')
def s3(self):
self.s2() obj=b()
obj.s3()
b

继承优先级:如果子类继承父类,对象在调用方法的时候,优先子类中找,如果有该方法执行该方法,如果没有在去父类找该方法。本质是:把父类的该方法拿到子类中,进行调用执行。

oop、configparser、xml模块

继承优先执行子类的中方法,如果子类中有该方法执行子类方法。

另一个思路:在执行self.xx的时候需要注意self是指执行对象,需要去执行对象的类型中去找,如果没有,再去父类找。

十一:多继承(python3中)

 class a:
def f2(self):
print('class a')
class b:
def f2(self):
print('class b')
class c(a,b):
def f3(self):
pass
obj=c()
obj.f2()
class a

多继承的时候,优先从左有到右。如上classc(a,b)子类c中没有方法f2,在去父类a,b中找,优先顺序 a  然后是b。从左到右顺序。

没有父类交叉的情况:

 class s1:
def f1(self):
print('s1')
class s2(s1):
def f2(self):
print('s2')
class s3:
def f1(self):
print('s3')
class s4(s2,s3):
def f2(self):
print('s4')
obj=s4()
obj.f1()
s1

当有纵向和横向的多继承时候,顺序:首先按继承顺序,从左到右优先级,先从对象的类中找,如果没有按对象类型的父类(从左右)中找,如果没有,去他的父类的父类中找,如果最后

没有的话,在找下一个对象的类父类平行的中父类中找,按照之前如果没有在去父类的父类找。。 如果没有在回到对象的类的平行父类中。。

oop、configparser、xml模块

父类有交叉的情况:

 class s_1:
def f2(self):
print('s_1')
class s0(s_1):
def f2(self):
print('s0')
class s1(s_1):
def f1(self):
print('s1')
class s2(s1):
def f1(self):
print('s2')
class s3(s0):
def f1(self):
print('s3')
class s4(s2,s3):
def f1(self):
print('s4')
obj=s4()
obj.f2() s0

oop、configparser、xml模块 优先没交集的父类,当这个2个都遍历照完之后在找交集部分,在去平行的父类找也就是第7步。代码如下:

 class s_1:
def f1(self):
print('s_1')
class s0(s_1):
def f1(self):
print('s0')
class s1(s_1):
def f1(self):
print('s1')
class s2(s1):
def f1(self):
print('s2')
class s3(s0):
def f1(self):
print('s3')
class s5:
def f2(self):
print('s5')
class s4(s2,s3,s5):
def f1(self):
print('s4')
obj=s4()
obj.f2()
s5

关于__init__构造方法:当对象创建的时候,会自动去自己类中找__init__构造方法,如果没有去父类找。如果有的话执行__init__方法。如果都没有就不执行该方法。

 class s1:
def __init__(self,name):
self.name=name
def show(self):
pass
class s2(s1):
def look(self):
pass obj=s2('evil')
print(obj.name)
evil

查找顺序和 多继承顺序是一样的。

模块:configparser 针对特殊配置文件进行操作。其本事是对文件的open()操作。

如下:

 [section1] # 节点
k1 = v1 # 值
k2:v2 # 值 [section2] # 节点
k1 = v1 # 值

操作:获取所有节点

 import  configparser

 con=configparser.ConfigParser()
con.read('1.txt',encoding='utf-8')
res=con.sections()
print(res)
['section1', 'section2']

获取指定节点下的key和值

 import  configparser

 con=configparser.ConfigParser()
con.read('1.txt',encoding='utf-8')
res=con.items('section1')
print(res)
[('k1', 'v1'), ('k2', 'v2')]

获取指定节点下的键值

 import  configparser

 con=configparser.ConfigParser()
con.read('1.txt',encoding='utf-8')
res=con.options('section1')
print(res)
['k1', 'k2']

获取指定节点指定值

 import  configparser

 con=configparser.ConfigParser()
con.read('1.txt',encoding='utf-8')
res=con.get('section1','k1')
print(res)
v1
 import  configparser

 con=configparser.ConfigParser()
con.read('1.txt',encoding='utf-8')
has_sec = con.has_section('section1')
print(has_sec) # 添加节点
con.add_section("sec_1")
con.write(open('1.txt', 'w')) # 删除节点
con.remove_section("sec_1")
con.write(open('1.txt', 'w'))
XML模块
xml是实现不同语言或程序之间进行数据交换的协议
格式如下:
 <data>
<country name="Liechtenstein">
<rank updated="yes"></rank>
<year></year>
<gdppc></gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank updated="yes"></rank>
<year></year>
<gdppc></gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes"></rank>
<year></year>
<gdppc></gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>

解析xml文件

 from xml.etree import ElementTree as E
str_xml = open('1.xml', 'r').read()# 打开文件,读取包含xml文件内容
root = E.XML(str_xml)# 将字符串解析成xml特殊对象,root代指xml文件的根节点
 from xml.etree import ElementTree as E
tree = E.parse("1.xml")# 直接解析1.xml文件
root = tree.getroot()# 获取xml文件的根节点

遍历xml文件的所有内容

 from xml.etree import ElementTree as E

 #第一种解析
"""
str_xml = open('1.xml', 'r').read()#打开文件读取1.xml文件
root = ET.XML(str_xml)#将字符串解析成xml特殊对象,root代指xml的根节点。
"""
# 第二种解析
# 直接解析xml文件
tree = E.parse("1.xml")
root = tree.getroot()#获取xml文件的根节点
# operation
print(root.tag)#最外层标签 for child in root:# 遍历1.xml的第二层
print(child.tag, child.attrib) # 第二层节点的标签名称和标签属性
for i in child:# 遍历XML文档的第三层
print(i.tag,i.text)# 第二层节点的标签名称和内容

因为修改的节点内容是修改在内存中的内容,需要把内存中内容写入文件中。

 from xml.etree import ElementTree as E

 # 直接解析xml文件
tree = E.parse("1.xml") # 获取xml文件的根节点
root = tree.getroot() #operation # 顶层标签
print(root.tag)
for i in root.iter('year'):# 循环year节点 new_year = int(i.text) + # 将year节点中的内容自增一
i.text = str(new_year) i.set('name', 'alex') # 设置属性
i.set('age', '')
del i.attrib['name']# 删除属性 #保存到文件中
tree.write("3.xml", encoding='utf-8')

删除节点操作:

 from xml.etree import ElementTree as E

 # 解析文件方式 

 # 直接解析xml文件
tree = E.parse("1.xml") root = tree.getroot()# 获取xml文件的根节点 #operation print(root.tag)#输出顶层标签
for country in root.findall('country'):# 遍历data下的所有country节点
rank = int(country.find('rank').text)# 获取每一个country节点下rank节点的内容
if rank > : root.remove(country)# 删除指定country节点
tree.write("2.xml", encoding='utf-8')# 保存文件