什么是XML
XML与JSON的对比
XML文档格式
使用XML模块解析
一,什么是XML
'''
XML 全称可扩展标记语言
<tag></tag> 双标签
<tag/> 单标签 没有文本 一般用于设计文档结构 例如:换行等
<tr/>表示换行
<tag style='color:red' age='18' >123456</tag>
一个标签的完整组成 有三个部分
tag 是标签名称
1234是文本内容 text
name = 'jack' 是标签的属性
其他的规范:
1,从开始就必须结束
2,所有属性值必须必须在双引号里面
3,只能有一个根标签 (最外层只能有一个标签)
4,开始标签和结束标签的顺序是相反的 ,最先打开谁,就最后关闭谁,最后打开的最先关闭
文档声明可不写,主要是告诉浏览器,该怎么解析这个文件
XML模块是自带的,不需要安装
与jsON的区别:
XML 是一种可扩展的标记语言
可以高度 自定义文档的结构,数据类型,标签的含义,使用场景广泛,不局限于前后台的数据交互,在其他语言中还经常作为配置文件来使用
所以扩展性远比JSON要强,XML用做数据交换格式的话,远不如json来的简单,JSON更加适用于前后台数据交换
JSON优点:
轻量级,跨平台,语法简洁
使用场景:多为前后台交互
XML更多用来作为配置文件,当然python不太常用,HXML也属于XML
总结,xml的解析比起json而言非常复杂 因为其扩展性远比json高,在java中常作为配置文件,当你在前后台进行数据交互时,优先使用json格式
'''''
1.**三个用于查找标签函数
iter("标签名") #全文查找
find("标签名") #查找子节点匹配的第一个
findall("标签名") #查找子节点匹配的所有标签
2.**访问标签的内容
element.tag 获取标签名
element.attrib 获取属性
element.text 获取文本
3.修改文档内容
elment.tag = "标签名"
element.text = "文本"
element.set("属性名","属性值")
4.删除节点
root.remove(标签对象)
5.添加子标签
#创建标签对象
year2=ET.Element('year2') # 指定名称
year2.text='新年'
year2.attrib={'update':'yes'}
#添加
country.append(year2) #往country节点下添加子节点
删除添加修改后都需要调用write写入到文件
tree.write("文件名"),#注意文档对象才能执行写入操作
import xml.etree.ElementTree as ET
#打开一个文档,得到一个元素树(XML文档)
tree = ET.parse('test.xml')
#获取根标签
root = tree.getroot()
print(root) #<Element 'data' at 0x000001FE7FBEDEA8>
#遍历出root标签的所有子标签
for tag in root:
print(tag)
#遍历出文档中所有标签
for tag in root.iter():
print(tag)
#从root下查找第一个名为country的子标签
country = root.find('country')
print(country) #<Element 'country' at 0x000001F46BA8C3B8>
#从root下查找所有名字为country的子标签
countrys = root.findall('country')
print(countrys)
#从root下查找所有名字为county的子孙标签
for tag in root.iter('country'):
print(tag)
'''
解析XML得到一个tree对象后,查找标签的4种方式
1,iter()
如果没有参数则查找所有标签
如果有参数则查找所有名字匹配的标签
查找范围 为全文
2,find()
必须给参数
查找当前标签的子标签,返回第一个名字匹配的
3,findall()
必须给参数
查找当前标签的子标签,返回所有名字匹配的
4,直接遍历某个标签
返回的是这个标签的所有子标签
'''
二,面向对象初识
### 什么是面向过程
首先明确一点,在面向对象之前我们一直都是按照面向过程的方式来编写程序!
面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式。
**优点是:复杂度的问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤将会非常简单)**
**缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身。**
**应用场景:一旦完成基本很少改变的场景,著名的例子有linux內核,git,以及Apache Http Server等。**
### 为什么需要面向对象?
当今时代背景下,通常应用程序对扩展性和维护性要求都是非常高的,为什么?想想qq,微信,是不是不断的在添加新功能?,也就是说一款应用程序诞生后,都需要不断的更新维护
### 什么是面向对象编程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。
它将对象作为程序的基本单元
<p style="color:red"> 将数据和处理数据的程序封装到对象中</p>
以提高软件的重用性、灵活性和扩展性为首要目的
### 面向对象编程优缺点
案例分析1:把大象装进冰箱如何实现
案例分析2:要开一家公司
**面向对象编程的优点:**
- 程序员的角色发送了改变,从一个操作者,变成了指挥者,不再需要关心,每个功能具体的实现细节,从而可以专注处理业务逻辑,是一种思想上的转变
- 大大提高了程序的扩展性,当一个对象发生了修改时,对其他对象时没有任何影响的,对象之间相互独立,耦合度变得更低了
- 提高了程序的灵活性,例如游戏中,每个玩家的操作都是自由的,而不是机械般固定的!你可以买武器,也可以买护甲
**缺点**:
- 编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度,如果用面向对象来设计linux,估计现在都没写完
- 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法准确地预测最终结果。
**应用场景**:
- 需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方
用一个例子来说明面向对象与面向过程的区别:
话说三国时期曹军于官渡大败袁绍,酒席之间,曹操诗兴大发,吟道:喝酒唱歌,人生真爽! 众将直呼:"丞相好诗",于是命印刷工匠刻板印刷以流传天下;
待工匠刻板完成,交与曹操一看,曹操感觉不妥,说道:"喝酒唱歌,此话太俗,应改为'对酒当歌'较好",于是名工匠重新刻板,当时还没有出现活字印刷术,如果样板要改,只能重新刻板,工匠眼看连夜刻版之工,彻底白费,心中叫苦不迭。可也只得照办。
版样再次出来请曹操过目,曹操细细一品,觉得还是不好,说”人生真爽太过直接,应该改问语才够意境,因此应改为‘对酒当歌,人生几何?’“,于是....
在活字印刷术还没出现之前,如果版样有改动,只能重新雕刻。而且在印刷完成后,这个样板就失去了它的价值,如果需要其他样板只能重新雕刻。而活字印刷术的出现就大大改善了印刷技术。
如上例”喝酒唱歌,人生真爽“,如果用活字印刷,只需要改四个字就可,其余工作都未白做。岂不快哉!!
活字印刷也反应了OOP。当要改动时,只需要修改部分,此为 可维护;当这些字用完后,并非就完全没有价值了,它完全可以在后来的印刷中重复使用,此乃 可复用;此诗若要加字,只需另刻字加入即可,这就是 可扩展;字的排列可以横排,也可以竖排,此是 灵活性好。
上述案列反应了OOP的优点,即可维护性高,扩展性强,复用性高! 这些特点非常适用于用户需求变化频繁的互联网应用程序,这是学习OOP的重要原因
但是OOP设计的程序需涉及类与对象,相应的复杂度会提高!
并非所有程序都需要较高的扩展性,例如系统内核,一旦编写完成,基本不会再修改,使用面向过程来设计则更适用
三,类与对象
类和对象是面向对象编程中最核心的两个概念
### 对象是什么
对象是特征与技能的结合体
如:演员张一山,姓名和职业是他的特征,演戏是他的行为,按照这样的定义,生活中到处都是对象
在程序中:
用变量来表示对象的特征,用函数表示对象的技能
<p style="color:red">将这些变量和函数结合在一起,形成一个整体,就是对象,这是面向对象的精髓所在!</p>
对象的另一种理解方式:
变量的作用数存储数据,函数的作用数处理数据
<p style="color:red">对象是将数据与处理数据的函数绑定在一起</p>
### 类是什么
类就是类型,类别,种类; 是一系列对象中相似特征与技能的结合体
在生活中是一种抽象概念,例如人类,是不具体的
如某个对象属于人类,可以通过类别,了解这个对象具备的特征和技能
反过来看类就是对象的模板,同一类的对象,具备相同的特征和行为
### 为什么需要类
现实生活中,通过对对象的分析总结,得到类型;用类型来标识不同对象之间的差异;
在程序中,同样用于标识不同对象之间的差异
另一个重要的功能是作为对象的模板,例如学生类,无论是哪个学生都具备学习这个方法,既然是相同的就没必要为每个对象单独编写,学生类负责提供这些相同的方法;
OOP第一步要做的就是定义需要的类
四,创建类和对象
## 定义类
以学生类Student为例,在Python中,定义类通过`class`关键字:
class Student:
pass
`class`后面紧接着是类名,即`Student`,遵循python编码规范,类名通常是大写开头的单词,多个单词时使用驼峰命名法
### 创建对象
创建对象也称之为实例化,定义好`Student`类后,就可以根据`Student`类创建出`Student`的实例,创建实例通过类名加上()实现:
stu1 = Student()
print(stu1)
#输出 <__main__.Student object at 0x10b11d588>
print(Student)
#输出 <class '__main__.Student'>
根据输出可以看到
变量名`stu1`指向一个`Student`类的实例,`0x10b11d588`是实例的内存地址,每个实例的地址都不相同,
Student`本身则是一个类`(class)
### 对象的属性操作
对象是特征(属性)与行为(方法)的结合体
`stu`这个对象目前不具备任属性和方法,要为其添加属性可以在创建对象后使用点语法`(变量名加 . ) `比如为`stu`对象添加name属性
stu1.name = "Jerry"
同样通过点语法来获取对象的属性值
print(stu1.name)
五,初始化方法init
### 什么是初始化方法
用于为对象的属性设置初始值的函数
### 为什么需要初始化方法
在类的实例(对象)中,一些属性是必须存在的,就可以使用初始化函数来完成,比如`Student`对象中的`name`属性,它是必须的,用于唯一标识一个学生
### 尝试一下
class Student:
def __init__ (self,name):
print("init run")
self.name = name
**执行过程:**
在创建对象时`Student("jack")`会申请新的内存空间用于保存对象数据,接着**自动调init函数**
**注意:**
`__init__`函数要求第一个参数必须是self,该参数表示需要被初始化的对象本身,这样就可以将name属性绑定到对象上
可以将self改为其他任意的名称,但为了保证易读性通常是self,额外的参数须位于self之后
有了`__init__`方法,在创建实例的时候,就不能传入空的参数了,必须传入与`__init__`方法匹配的参数,但`self`不需要传,Python解释器自己会把实例变量传进去:
# stu1 = Student()
# 以上代码将抛出异常:TypeError: __init__() missing 1 required positional argument: 'name'
stu1 = Student("jack")
# 输出 init run
print(stu1.name)
# 输出 jack
小结:
- init函数用于为对象属性设置初始值
- 在创建对象时会自动调用
- 自动传入对象本身
六,属性查找顺序
可以将类中的内容都称之为属性,变量称为数据属性,函数就叫函数属性
类中可以声明变量来表示数据属性,为`Student`类添加数据属性和函数属性
class Student:
school = "Tsinghua" #数据属性
def say_hello(self):#函数属性
print("hello i am a student")
def __init__ (self,name): #初始化函数
self.name = name
也可以使用点语法在创建对象后为对象增加数据属性
stu = Student("Maria")
stu.age = 20
问题1:在类中声明的数据属性和创建对象后为增加的数据属性,有什么区别?
类中的数据属性是所有对象共享的
创建对象后为增加的数据属性,是这个对象特有的,去其他对象无关
问题2:类中声明的数据属性和创建对象后为增加的数据属性,其访问属性是怎样的?
优先查找对象自己的名称空间,如果没有则在类中找,如果类中也没有则到父类中找,直到找到为止,如果父类中也没有则抛出异常
!!!注意!!!
此处父类可能也有父类,会一直沿着继承关系查找到最终的父类Object,该继承关系,后续会详细讨论!
案列:网页中折叠此处
stu1 = Student("Jack")
stu2 = Student("Rose")
#1.类中的数据属性是所有对象共享的
print(stu1.school)
print(stu2.school)
#输出 Tsinghua
#输出 Tsinghua
#2.类中的数据属性访问的是同一块内存
print(id(stu1.school))
print(id(stu2.school))
#输出 4470412656
#输出 4470412656
#3.类的函数属性是绑定给对象使用的,bound method称为绑定方法,每个对象的绑定方法内存地址不一样
print(stu1.say_hello)
print(stu2.say_hello)
#输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc405f8>>
#输出 <bound method Student.say_hello of <__main__.Student object at 0x10cc40630>>
#4.优先访问对象自己的名称空间
# 修改stu1的学习属性为北京大学 会在自stu1的名称空间增加school属性
stu1.school = "Beijing"
print(stu1.__dict__)
print(stu2.__dict__)
#输出 {'name': 'Jack', 'school': 'Beijing'}
#输出 {'name': 'Rose'}
#4.1再次查看学校属性
print(stu1.school)
print(stu2.school)
#输出 Beijing
#输出 Tsinghua
#__dict__用于访问对象的名称空间 本质是一个字典类型数据,存储名称与值的映射关系
属性查找顺序:对象->类->父类