Python中实战小案例


目录

  • Python中实战小案例
  • 一、正则表达式
  • 二、genent创建协程
  • 三、服务端使用http协议向浏览器发送消息
  • 四、深拷贝与浅拷贝
  • 五、类的继承
  • 5.1 单继承
  • 5.2 多继承
  • 5.3 使用super
  • 六、*arg与**kwargs传入参数
  • 七、计算分页的类
  • 八、property装饰器
  • 8.1 使用装饰器去调用
  • 8.2 使用方法去调用
  • 九、difflib模块比较文件内容
  • 9.1 实战:比较nginx的配置文件
  • 十、filecmp模块实现目录对比


一、正则表达式

匹配4-20位可以带字母数字下划线的126或者163邮箱,创建一个分组,用group(1)取值

ret = (re.match(r"[a-zA-Z_0-9]{4,20}@(163|126)\.com$", 'abcdd@126.com'))
print (ret.group())

验证手机号是否有效,只能匹配以1开头,第二位是3,长度为2+9=11的手机号

print(re.match(r'^1[3]\d{9}$','13345678401').group())

使用sub方法替换内容
第一种,直接替换

import re

ret = re.sub(r"\d+",str(100),"python = 99")
print(ret)

第二种,调用函数替换,两种输出都是一样的

import re

def add(temp):
    strNum = temp.group()
    num = int(strNum) +1
    return  str(num)


ret = re.sub(r"\d+",add,"python = 99")
print(ret)

结果:
python = 100

二、genent创建协程

genvnt: 在需要阻塞的代码处,自动切换下一个函数

注意:如果没有打补丁的话,耗时的代码不会切换另一个函数

代码如下:

import gevent
from gevent import  monkey
import time

monkey.patch_all()  # 将程序中所用到的所有耗时操作的代码打上gevent的补丁
def work1(num):
    ret=0
    for i in range(num):
        print(ret,'work1')
        ret+=1
        time.sleep(1)

def work2(num):
    ret=0
    for i in range(num):
        print(ret,'work2')
        ret+=1
        time.sleep(1)
gevent.joinall(
    [
        gevent.spawn(work1,5),
        gevent.spawn(work2,5)
    ]
)

运行结果:

0 work1
0 work2
1 work1
1 work2
2 work1
2 work2
3 work1
3 work2
4 work1
4 work2

三、服务端使用http协议向浏览器发送消息

浏览器作为客户端

代码原理:

  • 创建套接字,监听7788端口
  • 浏览器请求根目录返回主界面代码,请求文件则打开文件并返回给浏览器
  • 若请求文件不存在,则返回404
  • qq浏览器犯病,有时候请求体为空,所以加了一个判断,判断是否存在请求体

代码如下:

import logging
import os.path
import re
import socket

Format = logging.Formatter('%(levelname)s  %(asctime)s %(filename)s  %(funcName)s [%(message)s] ')
logger = logging.getLogger()
logger.setLevel('DEBUG')
console_handle = logging.StreamHandler()
console_handle.setLevel(level='INFO')
console_handle.setFormatter(Format)
logger.addHandler(console_handle)


def send_main(new_tcp_socket):
    logger.info('request main')
    responce = 'HTTP/1.1 200 OK\r\n'
    responce += "\r\n"
    send_data = "<h1>I am a cute server</h1>"
    logger.info(f'sending data: {send_data}')
    new_tcp_socket.send((responce + send_data).encode('utf-8'))


def send_responce(new_tcp_socket):
    request = new_tcp_socket.recv(1024).decode('utf-8')
    if request:
        request_lines = request.splitlines()
        logger.debug(request_lines)
        ret = re.match(r"[^/]+/([^ ]*)", request_lines[0]).group(1)
        if ret:
            logger.info(f'request file = {ret}')
            if os.path.exists(ret):
                with open(ret, 'rb') as file:
                    send_data = file.read().decode('utf-8')
                    responce = 'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n'
                    responce += "\r\n"
                    logger.info(f'sending file content: {file}')
                    new_tcp_socket.send((responce + send_data).encode('utf-8'))
            else:
                responce = 'HTTP/1.1 404 Not Found\r\nContent-Type: text/html; charset=utf-8\r\n'
                responce += "\r\n"
                logger.error('file not exists')
                new_tcp_socket.send((responce + '<h1>file not exists</h1>').encode('utf-8'))
        else:
            send_main(new_tcp_socket)
    else:
        logger.error('QQ  browser disease')
        send_main(new_tcp_socket)
    new_tcp_socket.close()
    logger.info('close connection')


def main():
    logger.info('start listen port:7788')
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.bind(('', 7788))
    tcp_server_socket.listen(128)
    while True:
        logger.info('reday for a new connection')
        new_tcp_socket, client_addr = tcp_server_socket.accept()
        logger.info(f'client has established a connection.client addr = {client_addr}')
        send_responce(new_tcp_socket)


if __name__ == '__main__':
    main()

成果展示:

python课堂基础问题讨论_html


python课堂基础问题讨论_python_02


后台日志:

python课堂基础问题讨论_python课堂基础问题讨论_03

四、深拷贝与浅拷贝

import copy

print('----------浅拷贝----------')
a=[1,2,3]
b=[4,5,6]
c=[a,b]
d=copy.copy(c)
print('c的值与id为',c,id(c))
print('d的值与id为',d,id(d))
print('a的id为',id(a))
print('d中第一个元素的id为',id(d[0]))
print('a中添加元素777')
a.append(777)
print(f'c的值为{c},d的值为{d}')
print()

print('----------深拷贝----------')
a=[1,2,3]
b=[4,5,6]
c=[a,b]
d=copy.deepcopy(c)
print('c的值与id为',c,id(c))
print('d的值与id为',d,id(d))
print('a的id为',id(a))
print('d中第一个元素的id为',id(d[0]))
a.append(777)
print(f'c的值为{c},d的值为{d}')

结果:

----------浅拷贝----------
c的值与id为 [[1, 2, 3], [4, 5, 6]] 2962023748352
d的值与id为 [[1, 2, 3], [4, 5, 6]] 2962023748608
a的id为 2962014350272
d中第一个元素的id为 2962014350272
a中添加元素777
c的值为[[1, 2, 3, 777], [4, 5, 6]],d的值为[[1, 2, 3, 777], [4, 5, 6]]

----------深拷贝----------
c的值与id为 [[1, 2, 3], [4, 5, 6]] 2962023743424
d的值与id为 [[1, 2, 3], [4, 5, 6]] 2962023748352
a的id为 2962023748096
d中第一个元素的id为 2962023743168
c的值为[[1, 2, 3, 777], [4, 5, 6]],d的值为[[1, 2, 3], [4, 5, 6]]

五、类的继承

5.1 单继承

python课堂基础问题讨论_html_04

5.2 多继承

父类被继承了几次就会被调用几次

class Persion(object):
    def __init__(self, name):
        print('presion主类的init方法被调用')
        self.name = name
        print('presion主类的init方法结束调用')


class son1(Persion):
    def __init__(self, name, age):
        print('son1的init方法被调用')
        self.age = age
        Persion.__init__(self, name)
        print('son1的init方法结束调用')


class son2(Persion):
    def __init__(self, name, gender):
        print('son2的init方法被调用')
        self.gender=gender
        Persion.__init__(self, name)
        print('son2的init方法结束调用')


class all(son1, son2):
    def __init__(self, name, age, gender):
        print('all 的init被调用')
        son1.__init__(self, name, age)
        son2.__init__(self, name, gender)
        print('all的init方法结束调用')


stu1 = all('小张', 20, 'man')
print(f'姓名:{stu1.name},年龄:{stu1.age},性别{stu1.gender}')

执行结果:

all 的init被调用
son1的init方法被调用
presion主类的init方法被调用
presion主类的init方法结束调用
son1的init方法结束调用
son2的init方法被调用
presion主类的init方法被调用
presion主类的init方法结束调用
son2的init方法结束调用
all的init方法结束调用
姓名:小张,年龄:20,性别man

5.3 使用super

这段我也蒙了,先记录一下代码吧

class Persion(object):
    def __init__(self, name):
        print('presion主类的init方法被调用')
        self.name = name
        print('presion主类的init方法结束调用')


class son1(Persion):
    def __init__(self, name, age, *args, **kwargs):
        print('son1的init方法被调用')
        self.age = age
        super().__init__(name, *args, **kwargs)
        print('son1的init方法结束调用')


class son2(Persion):
    def __init__(self, name, gender, *args, **kwargs):
        print('son2的init方法被调用')
        self.gender = gender
        super().__init__(name, *args, **kwargs)
        print('son2的init方法结束调用')


class all(son1, son2):
    def __init__(self, name, age, gender):
        print('all 的init被调用')
        super().__init__(name, age, gender)
        print('all的init方法结束调用')


stu1 = all('小张', 20, 'man')
print(all.__mro__)
print(f'姓名:{stu1.name},年龄:{stu1.age},性别{stu1.gender}')

执行结果:

all 的init被调用
son1的init方法被调用
son2的init方法被调用
presion主类的init方法被调用
presion主类的init方法结束调用
son2的init方法结束调用
son1的init方法结束调用
all的init方法结束调用
(<class '__main__.all'>, <class '__main__.son1'>, <class '__main__.son2'>, <class '__main__.Persion'>, <class 'object'>)
姓名:小张,年龄:20,性别man

六、*arg与**kwargs传入参数

args保存到元组,kwargs保存到列表

def worker(a,b,*args,**kwargs):
    print(a,b,args,kwargs)

worker('asdsadas',"a4",23,56,name='laowang')

运行结果:

asdsadas a4 (23, 56) {'name': 'laowang'}

注意:如果要给另一个函数传递变量,请使用下图的写法

python课堂基础问题讨论_python课堂基础问题讨论_05

七、计算分页的类

class Pager:
    def __init__(self, current_page) -> None:
        self.current_page = current_page
        self.per_items = 10

    @property
    def start(self):
        val = (self.current_page -1 ) * self.per_items
        return val
    
    @property
    def end(self):
        val = self.current_page * self.per_items
        return val


p=Pager(2)
print(p.start,p.end)

执行结果:
10 20

八、property装饰器

定义装饰器共有两种方式,分别是【装饰器】与【类属性】,而装饰器方式针对经典类与新式类又有所不同;

通过property属性,能够简化调用者在获取数据的流程

8.1 使用装饰器去调用

class Godds(object):
    def __init__(self, cur_prise) -> None:
        self.cur_prise = cur_prise

    @property
    def say(self):
        print('property:' , self.cur_prise)
    
    @say.setter
    def say(self,value):
        self.cur_prise=value
    
    @say.deleter
    def say(self):
        print('del')
        del self.cur_prise
    
    

a = Godds(20)
a.say  #获取
a.say=30  # 修改
del a.say  # 删除
a.say

8.2 使用方法去调用

python课堂基础问题讨论_开发语言_06

九、difflib模块比较文件内容

import difflib
a1='hahahahha \n pipipipi'
a2='hahahaeee \n pipipipi'

# 创建对象
d=difflib.Differ()
# 生成不同内容
diff=d.compare(a1,a2)
print('\n'.join(list(diff)))


# 生成精美的html文件
html_diff=difflib.HtmlDiff()
html_result=html_diff.make_file(a1,a2)
with open ('./html_result.pdf','w') as f :
    f.write(html_result)

python课堂基础问题讨论_python课堂基础问题讨论_07

9.1 实战:比较nginx的配置文件

import difflib
import sys

# 获取变量
try:
    conf_file1=sys.argv[1]
    conf_file2=sys.argv[2]
except Exception as e:
    print(e)

# 读取文件
def readfile(filename):
    try:
        with open(filename,'r') as f:
            text = f.read().splitlines()
            return text
    except Exception as e :
        print(e)

if conf_file1 == '' or conf_file2 == '':
    print ('文件为空') 
    sys.exit()

# print(conf_file1,conf_file2)
text1=readfile(conf_file1)
text2=readfile(conf_file2)

diff_object = difflib.HtmlDiff()
diff_result = diff_object.make_file(text1,text2)


with open('nginx_diff.html','w') as f :
    f.write(diff_result)

python课堂基础问题讨论_python课堂基础问题讨论_08

十、filecmp模块实现目录对比

介绍都在代码注释里,所以直接上代码

import filecmp

# 文件对比

def file_compare():
# 返回一个元祖,第一组是相同的,第二组是不同的,第三组是独有的  
    result = filecmp.cmpfiles("/root/python/2022-0307","/root/python/demo",['demo1.txt','demo2.txt','demo3.txt','demo4.txt'])
    print(result) # (['demo1.txt'], ['demo2.txt'], ['demo3.txt', 'demo4.txt'])

# 文件夹对比

def dir_compare():
    dir1 = "/root/python/2022-0307/dir1"
    dir2 = "/root/python/2022-0307/dir2"
    # 实现目录的比对,忽略普通文件demo2.txt
    dir_obj = filecmp.dircmp(dir1,dir2,['demo2.txt'])
    # 仅输出一级目录
    dir_obj.report()
    # 仅输出一级目录及一级目录下的效果
    dir_obj.report_partial_closure()
    # 输出所有目录信息的效果
    dir_obj.report_full_closure()
    # 输出相同目录
    #print("共同存在的目录:{}".format(dir_obj.common_dirs))
    print("共同存在的文件:{}".format(dir_obj.common_files))
    
    print("不共同存在的文件:{}".format(dir_obj.diff_files))
dir_compare()