python周报第七周

0.知识点预览

  • configparse、XML、zipfile、tarfile
  • 面向对象基础

1.模块进阶

1. configparser

liukai@bogon:~/PycharmProjects/s13/day7$ cat testfile
[info1]
name = liukai
age1 = 19

[info2]
name = lk
age1 = 22

 

import configparser

config=configparser.ConfigParser()
config.read("testfile",encoding="utf-8")
sec = config.sections()
print("sec:",sec)
k = config.items("info1")
print("k:",k)
v = config.options("info2")
print("v:",v)
vv = config.get("info1",'name')
print("vv:",vv)
if_suc = config.has_section("info1")
if_suc2 = config.has_section("info4")
print(if_suc,if_suc2)

执行结果如下:

sec: ['info1', 'info2']
k: [('name', 'liukai'), ('age1', '19')]
v: ['name', 'age1']
vv: liukai
True False

代码剖析:read()方法:选择读取哪个文件;sections()方法:选择配置文件中的主节点;items()方法:选择特定主节点的信息,参数是节点名;options()方法:得到某个主节点的某个key的值;has_section()方法,判断配置文件是否有某个主节点。

liukai@bogon:~/PycharmProjects/s13/day7$ cat testfile
[info1]
name = liukai
age = 19

[info2]
name = lk
age1 = 22
import configparser

config=configparser.ConfigParser()
config.read("testfile",encoding="utf-8")
config.add_section("info3")
config.write(open("testfile","w"))
print(config.has_section("info3"))
config.remove_section("info2")
config.write(open("testfile","w"))
print(config.has_section("info2"))
has_k = config.has_option("info1","name")
print(has_k)
config.remove_option("info1","age")
print(config.get("info1","name"))
config.set("info1","age1","39")
config.write(open("testfile","w"))

执行结果如下:

True
False
True
liukai
liukai@bogon:~/PycharmProjects/s13/day7$ cat testfile
[info1]
name = liukai
age1 = 39

[info3]

代码剖析:重复的方法上面有,configparser的操作都是在内存中操作的,假如想使其生效,需要把内存的数据刷到硬盘上。write()方法就是这个功能。remove_sections()方法是删除整个主节点,连带其下面的数据都会删除。get()方法:获取主节点的某个key的值。set()方法:设置某个主节点的某个key的值。PS:假如没用write()方法,文件是不会被修改的。

2.xml相关模块

1.解析XML

解析XML:

方法一:

from xml.etree import ElementTree as ET

tree = ET.parse("testxml")
root = tree.getroot()
print(root.tag)
for child in root:
    for grantchild in child:
        print(grantchild.tag,grantchild.attrib,grantchild.text)

方法二:

from xml.etree import ElementTree as ET

str_xml = open("testxml","r").read()
root = ET.XML(str_xml)
print(root.tag)
for child in root:
    for grantchild in child:
        print(grantchild.tag,grantchild.attrib,grantchild.text)
liukai@bogon:~/PycharmProjects/s13/day7$ cat testxml
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

执行结果如下:

/usr/bin/python3 /Users/liukai/PycharmProjects/s13/day7/test.py
data
rank {'updated': 'yes'} 2
year {} 2023
gdppc {} 141100
neighbor {'direction': 'E', 'name': 'Austria'} None
neighbor {'direction': 'W', 'name': 'Switzerland'} None
rank {'updated': 'yes'} 5
year {} 2026
gdppc {} 59900
neighbor {'direction': 'N', 'name': 'Malaysia'} None
rank {'updated': 'yes'} 69
year {} 2026
gdppc {} 13600
neighbor {'direction': 'W', 'name': 'Costa Rica'} None
neighbor {'direction': 'E', 'name': 'Colombia'} None

代码分析:解析XML有两种方法,一是直接解析xml文件;二是解析字符串类型的xml。这两种方法有一点不同,解析文件的形式可以直接修改xml,而字符串的形式也需要利用解析文件的方法修改xml到文件。parse()方法是解析文件。XML()方法是解析字符串。getroot()方法:获取根节点。

2.修改XML

liukai@bogon:~/PycharmProjects/s13/day7$ cat testxmlnew2
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc age="44" name="fuck">141105</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc age="44" name="fuck">59905</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc age="44" name="fuck">13605</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>
from xml.etree import ElementTree as ET
tree = ET.parse("testxml")
root = tree.getroot()
print(root.tag)
for i in root.iter("gdppc"):
    new_gdppc = int(i.text) + 5
    i.text = str(new_gdppc)

    i.set("name","fuck")
    i.set("age","88")
    print(i.attrib,i.text,i.tag)

tree2 = ET.ElementTree(root)
tree2.write("testxmlnew2",encoding="utf-8")

执行结果如下:

data
{'name': 'fuck', 'age': '88'} 141105 gdppc
{'name': 'fuck', 'age': '88'} 59905 gdppc
{'name': 'fuck', 'age': '88'} 13605 gdppc
liukai@bogon:~/PycharmProjects/s13/day7$ cat testxmlnew2
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc age="88" name="fuck">141105</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc age="88" name="fuck">59905</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc age="88" name="fuck">13605</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

代码解析:iter()方法:在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器,ElementTree(root):保存文件。在这之前的所有操作都是在内存中执行的,只有ElementTree后才保存到文件。

3.生成XML

from  xml.etree import ElementTree as ET
from xml.dom import minidom
def prettify(elem):
    """将节点转换成字符串,并添加缩进。
    """
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")


root = ET.Element("family")

son1 = ET.Element('son1',{"name":"son11"})
son2 = ET.Element('son2',{"nane":"son22"})

grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson2 = ET.Element('grandson', {'name': '儿12'})
son1.append(grandson1)
son1.append(grandson2)

root.append(son1)
root.append(son1)
raw_str = prettify(root)
f = open("family.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close()

执行结果如下:

liukai@bogon:~/PycharmProjects/s13/day7$ cat family.xml
<?xml version="1.0" ?>
<family>
    <son1 name="son11">
        <grandson name="儿11"/>
        <grandson name="儿12"/>
    </son1>
    <son1 name="son11">
        <grandson name="儿11"/>
        <grandson name="儿12"/>
    </son1>
</family>

代码解析:prettify函数将节点转换成字符串,并添加缩进。在创建XML时,要把内层数据加到外层数据中,如:root.append(son1)这样。

3.zipfile、tarfile

1.zipfile

import zipfile

# 压缩
z = zipfile.ZipFile('lk.zip', 'w')
z.write('a.log')
z.write('b.txt')
z.close()

# 解压
z = zipfile.ZipFile('lk.zip', 'r')
z.extractall()
z.close()

执行结果如下:

liukai@bogon:~/PycharmProjects/s13/day7$ ls lk.zip
lk.zip
liukai@bogon:~/PycharmProjects/s13/day7$ unzip lk.zip
Archive:  lk.zip
 extracting: a.log
 extracting: b.txt

代码解析:ZipFile():创建一个压缩包,write():添加文件到压缩包。extractall():解压所有包。

2.tarfile

import tarfile

# 压缩
tar = tarfile.open('lk.tar','w')
tar.add('a.log', arcname='aaaa.log')
tar.add('b.txt', arcname='bbbb.txt')
tar.close()

# 解压
tar = tarfile.open('lk.tar','r')
tar.extractall()  # 可设置解压地址
tar.close()

执行结果如下:

liukai@bogon:~/PycharmProjects/s13/day7$ tar xf lk.tar
liukai@bogon:~/PycharmProjects/s13/day7$ ls aaaa.log bbbb.txt
aaaa.log bbbb.txt

代码解析:tarfile.open(),创建一个压缩包,add():添加文件到压缩包,可以改名。extractall():解压。

4.初识面向对象

1.面向对象与函数式编程

def mail(content):
    print("利用函数,已发出邮件,内容为%s" % content)


mail("hello")

class Mail:
    def mail(self,content):
        print("利用类,已发出邮件,内容为%s" % content)

m = Mail()
m.mail("fuck")

执行结果如下:

利用函数,已发出邮件,内容为hello
利用类,已发出邮件,内容为fuck

代码解析:用函数式编程,直接调用函数即可,用面向对象编程,需要先实例化一个对象,用对象来调用类里的方法。

结论:什么时候用面向对象?当某一些函数具有相同参数时,可以使用面向对象的方式,将参数值一次性的封装到对象,以后去对象中取值即可。

2.面向对象基础

1.创建类和对象

class Mail:
    def mail(self,content):
        print("利用类,已发出邮件,内容为%s" % content)

m = Mail()
print(type(Mail))

执行结果如下:

<class 'type'>

代码解析:创建类的格式:class 类名;创建类中方法的格式:def 方法名(self,xxx);实例化对象的格式:对象名 =  类名(),利用对象执行方法:对象名.方法名(123)

2.__init__()

class Mail:

    def __init__(self,name,addr):
        self.name = name
        self.addr = addr

    def mail(self,content):
        print("[%s]利用类,已发出邮件,内容为%s,到[%s]" % (self.name,content,self.addr))

m = Mail("lk","SB")
m.mail("fuck")

执行结果如下:

[lk]利用类,已发出邮件,内容为fuck,到[SB]

代码解析:__init__方法是类的构造方法,当执行类名()的时候,__init__方法会被自动执行。一般在初始数据的时候需要用到,类中的每个函数的第一个参数都是self,这是规定,这个self会被自动赋给对象本身。当代码执行到 m = Mail()的时候,会实例化一个对象,这个对象m 就被赋给所有的self,在__init__方法初识化后,以便其他方法比如mail()方法调用。

3.类的继承

1.类调用关系

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 = C2("liukai","22")
c1 = C1("lk",c2)
c3 = C3(c1)

print(c1.obj.age)
print(c1.obj.name)

c3.aaa.obj.show()

执行结果如下:

22
liukai
liukai

代码解析:创建了三个类,C1、C2、C3;每个类都有构造方法,其中类C2有个show()方法。当执行到c2 = C2("liukai","22")时:实例化类C2的一个对象c2;c1 = C1("lk",c2)时:self.name = lk;self.obj = c2;c3 = C3(c1):self.aaa = c1;当执行到print(c1.obj.age)时,c1.obj = c2 ;c1.obj.age == c2.age,所以打印22,同理c1.obj.name 打印liukai,c3.aaa.obj.show():c3.aaa == c1,相当于c1.obj.show(),c1.obj == c2,故c2.show()打印的是c2.name == liukai

2.初识继承

class F1:
    def show(self):
        print("show")

    def foo(self):
        print(self.name)

class F2(F1):
    def __init__(self,name):
        self.name = name

    def bar(self):
        print("bar")

    def show(self):
        print("F2.show")

obj = F2("lk")
obj.foo()

执行结果如下:

lk

代码解析:F1为父类,子类继承父类的格式:class 子类名(父类名1,父类名2....),python支持多继承,这是和其他语言不同的地方。当执行obj = F2("lk")的时候,首先自动执行F2的__init__方法。obj.name = lk;当执行obj.foo()方法时,首先在F2类找,没有找到,便去其父类F1中找。找到foo()方法,因为self = obj,打印obj.name == lk

2.继承进阶

下面利用sockerserver源码来分析类继承的顺序。

import socketserver
obj = socketserver.ThreadingTCPServer()
obj.serve_forever()

代码解析:导入socketserver模块,执行obj = sockerserver.ThreadingTCPServer(),假如ThreadingTCPServer()是个方法,就直接执行这个方法,假如这是个类,则就去找这个类的源码,要执行__init__()方法

class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

发现ThreadingTCPServer类无内容,继承了ThreadingMinIn类和TCPServer类,优先继承ThreadingMinIn。所以先去找ThreadingMinIn()源码

class ThreadingMixIn:
    """Mix-in class to handle each request in a new thread."""

    # Decides how threads will act upon termination of the
    # main process
    daemon_threads = False

    def process_request_thread(self, request, client_address):
        """Same as in BaseServer but as a thread.

        In addition, exception handling is done here.

        """
        try:
            self.finish_request(request, client_address)
            self.shutdown_request(request)
        except:
            self.handle_error(request, client_address)
            self.shutdown_request(request)

    def process_request(self, request, client_address):
        """Start a new thread to process the request."""
        t = threading.Thread(target = self.process_request_thread,
                             args = (request, client_address))
        t.daemon = self.daemon_threads
        t.start()

发现ThreadingMinIn类并无__init__()方法,则去找另一个父类TCPServer(),以下是TCPServer()的源码

class TCPServer(BaseServer):

    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    request_queue_size = 5

    allow_reuse_address = False

    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)

发现TCPServer有__init__方法,则执行这个方法。obj = sockerserver.ThreadingTCPServer() 这条语句执行完毕,执行下一条:obj.serve_forever();依旧去找

 ThreadingTCPServer()的源码,去找serve_forever方法,发现没有该方法,去父类ThreadingMixIn找,也未找到,去父类TCPServer()类去找,也未找到,则去TCPServer()的父类BaseServer()去找,找到了serve_forever()方法。在该方法内,还执行了self._handle_request_noblock()。当执行self.xxxx方法时,这个self就等于obj,所以还要从最开始ThreadingTCPServer()找。按照刚才的方法找,从BaseServer()类中找到了该方法,在该方法内还要执行self.process_request()方法,虽然说这个类中有此方法,不过还要从头找。最后在ThreadingMixIn()类中就找到了,优先级高于BaseServer()类中的方法。

结束:这就是类的继承顺序。

转载于:https://www.cnblogs.com/Caesary/p/5599937.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值