zoukankan      html  css  js  c++  java
  • 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="	")
    
    
    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()类中的方法。

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

  • 相关阅读:
    去掉Win10中的“此电脑”中的6个默认文件夹的方法
    Fastboot驱动及安装
    Fastboot驱动及安装
    JNI+NDK编程总结
    JNI+NDK编程总结
    20194742自动生成四则运算题第一版报告
    读构建之法现代软件工程随笔
    想法或创意
    ubuntu控制台乱码
    Java 为什么不支持多继承?
  • 原文地址:https://www.cnblogs.com/Caesary/p/5599937.html
Copyright © 2011-2022 走看看