面向对象多重继承、简单的版本控制、进程/线程、网络编程

面向对象 - 多重继承(一个类继承多个类)

  • 如果一个类有多个父类,而多个父类又有公共的父类(菱形/砖石继承)
    那么在搜索属性和方法时搜索的依据是c3算法(类似于广度优先搜索)
    这个是Python3中的一个改进,在此之前搜索的额算法是深度优先搜索(DFS)
  • 在实际开发尽量避免多重继承,无法避免的时候可以把除第一父类外的父类设定为抽象类,子类在继承的时候重写方法
from abc import ABCMeta,abstractmethod

class Father(object):

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

    def drink1(self):
        print(self._name + '正在喝酒')

    def gamble(self):
        print(self._name + '正在赌博')

class Monk(object, metaclass=ABCMeta):

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

    @abstractmethod
    def eat_vegetable(self):
        pass

    @abstractmethod
    def chant(self):
        pass

class Musicion(object, metaclass=ABCMeta):

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

    @abstractmethod
    def drink2(self):
        pass

    @abstractmethod
    def play_piano(self):
        pass

class Son(Father, Monk, Musicion):

    def __init__(self, name, nickname, artname):
        Father.__init__(self, name)
        self._nickname = nickname
        self._artname = artname

    def play_piano(self):
        print(self._artname + '正在弹钢琴')

    def read(self):
        print(self._nickname + '正在念经')

    def drink1(self):
        print(self._name + '正在喝五粮液')

    def drink2(self):
        print(self._artname + '正在喝王老吉')

def main():
    son = Son('盖小伦', '智空', '银河之力')
    son.drink()
    # Musicion.drink(son)
    son.chant()
    son.play_piano()

if __name__ == '__main__':
    main()

版本控制Subversion(集中控制) / Git(分布控制)

  • 使用Git版本控制操作步骤:
    命令提示符进入需要版本控制的文件夹
    git init # 初始化,建成仓库,可以记录历史版本
    git add .(导入当前文件夹所有文件) # git add test007.py只导入test007.py这个文件
    git status # 查看修改后的结果/状态
    git commit -m ‘修正了一个bug’ #说明修改原因(本地版本控制)
    git remote add origin https//…. # 与远端仓库建立联系
    git push origin master # 推送到远程仓库

概要1:git init - git add . - git status - git commit -m ‘提交原因’ (本地版本控制)
2: git clone https…实际开发中可以先建好远程仓库,拷贝到本地后再开始编辑以及推送到远程仓库
3: 远端git remote add origin https//… - git pull https//…(远端仓库拉到本地)- git push origin master…(推送到远端仓库)

  • 常用命令
    git pull – cat test007.py # 查看当前文档内容
    git branch查看分支 git branch new_function建立新分支 git merge new-function合并分支 git branch -d new-function rm
    cls # 清屏
    cd ./cd .. # 回到当前/上一级目录
    pwd # print work d…打印当前工作目录
    ls -a #查看仓库所有文件
    git log # 查看历史版本/日志
    git reset # 回到初始版本
    git checkout data.json # 恢复删除的文件
    git clon \http:…. # 克隆云端文件

正则表达式

正则表达式就是记录文本规则的代码,定义字符串的匹配模式。

  • 常用元字符(代表字符串的开头和结尾,它只匹配一个位置)
    . 匹配除换行符以外的任意字符
    \w 匹配字母或数字或下划线或汉字
    \s 匹配任意的空白符
    \d 匹配数字
    \b 匹配单词的开始或结束
    ^ 匹配字符串的开始
    $ 匹配字符串的结束

  • 常用限定符(指定数量的代码)
    *重复零次或更多次
    +重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次

  • 常用反义符
    \W 匹配任意不是字母,数字,下划线,汉字的字符
    \S 匹配任意不是空白符的字符
    \D 匹配任意非数字的字符
    \B 匹配不是单词开头或结束的位置
    [^x] 匹配除了x以外的任意字符

  • 常用分组语法
    (exp) 匹配exp,并捕获文本到自动命名的组里
    (?< name >exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
    (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
    (?=exp) 匹配exp前面的位置
    (?<=exp) 匹配exp后面的位置
    (?!exp) 匹配后面跟的不是exp的位置
    (? < !exp) 匹配前面不是exp的位置

import re  # 导入正则表达式模块

def main():
    username = 'someone'
    m = re.match(r'^\w{6,20}$', username)
    print(m)  # 如果匹配失败,返回None
    if m:
        print(m.span())  # 如果匹配成功,拿到匹配的范围
        print(m.group())  # 把匹配到的范围取出来


if __name__ == '__main__':
    main()

我们玩游戏的时候有些敏感字是不能被输出的,这时候就可以用*来代替

import re

def main():
    re.sub  # substitute替换
    sentence = '赵信我操你大爷干你二爷Fuck你姑爷'
    pure = re.sub('[艹草操日干肏]|赵信|fuck|shit|傻逼', '*', sentence,
                  flags=re.IGNORECASE)  # |分支,  flags标记IGNORECASE忽略大小写
    print(pure)  # 输出"*我*你大爷*你二爷*你姑爷"


if __name__ == '__main__':
    main()

process进程,thread线程

  • 进程是操作系统分配内存的基本单元,进程之间的内存是相互隔离的,通过icp机制/管道通信。
    一个进程可以划分为多个线程,线程是进程的执行单元 ,也是操作系统分配cpu的执行单元;线程启用的越多,占用cpu越多。

    使用多线程/多进程可以提升执行效率,缩短程序执行时间;改善用户体验。

  • python中使用多进程比多线程更好,因为多进程相互之间是独立的,程序执行效率更高。

进程

from multiprocessing import Process
import subprocess  # subprocess子进程
import time
import os

def output():
    print(os.getpid())  # 启用多进程
    while True:
        print('Pong', end = '', flush=True)  # flush=True关闭缓存
        time.sleep(0.001)

def main():
    print(os.getpid)  # 打印进程号
    p = Process(target=output)  # 这里传入函数名,表示进程启用后才在这个进程里面去执行函数
    p.start()
    while True:
        print('Ping', end = '', flush=True)
        time.sleep(0.001)

def main():
    subprocess.call('calc')  # call调用calc计算器
    subprocess.call('notepad')


if __name__ == '__main__':
    main()

线程

  • 多线程是共享内存的,共享数据。
    python不能用到cpu的多核特性,但是这不代表他的多进程、多线程是无用的。
    实际开发中,多线程的程序不好写,也不好调试,因为cpu分配是随机的,运行时如果有bug那么就不知道它什么时候回出现问题。
  • 创建线程的两种方式:
    1,直接创建Thread对象并通过target参数指定线程启动后要执行的任务。
    2,继承Thread自定义线程,通过重写run方法指定线程启动后执行的任务,推荐使用这种方法!
from threading import Thread  # from thread是python2中使用的模块
from time import sleep

def output():
    while True:
        print('Pong', end='', flush=True)
        sleep(0.001)

def main():
    t1 = Thread(target=output)
    t1.start()
    while True:
        print('Ping', end='', flush=True)
        sleep(0.001)

if __name__ == '__main__':
    main()
from time import sleep

def output(string):
    while True:
        print(string, end='', flush=True)
        sleep(0.001)

def main():
    # 这里应该使用元组,并且尽管只有一个元素,但是也要加上逗号,否则就是一个字符串
    t1 = Thread(target=output, args=('Ping',))
    t1.start()
    t2 = Thread(target=output, args=('Pong',))
    t2.start()

if __name__ == '__main__':
    main(
from threading import Thread
from time import sleep

def output(string):
    while True:
        print(string, end='', flush=True)
        sleep(0.001)

def main():
    # daemon=True - 将线程设置为守护线程(不值得保留的线程),其他线程/主程序如果执行完了,那么守护线程自动结束
    t1 = Thread(target=output, args=('Ping',),daemon=True)
    t1.start()
    t2 = Thread(target=output, args=('Pong',), daemon=True)
    t2.start()

if __name__ == '__main__':
    main()

多进程模拟下载文件
如果多个任务之间没有任何的关联(独立子任务),而且希望利用cpu的多核特性,那么我们推荐使用多进程,因为任务之间没有数据交换

import time
import random
from threading import Thread


def download(filename):
    print('开始下载%s...' % filename)
    delay = random.randint(5,15)
    time.sleep(delay)
    print('%s下载完成,用时%d秒' % (filename, delay))

# 如果要写多线程,推荐使用这种方法
class DownloadTask(Thread):

    def __init__(self, filename):
        super().__init__()
        self._filename = filename

    # 钩子函数(hook) / 回调函数(callback)(写了这个方法,但是从来没有调用它,它是让系统启动线程的时候自动回调这个方法)
    # 写程序时启用线程用start,不能用run!!!
    def run(self):
        download(self._filename)

def main():
    start = time.time()
    t1 = DownloadTask('Python从入门到住院.pdf')
    t1.start()
    t2 = DownloadTask('Pekin Hot.avi')
    t2.start()
    t1.join()  # join等待进程结束(然后再打印时间)
    t2.join()
    end = time.time()
    print('总共耗费了%f秒' % (end - start))


if __name__ == '__main__':
    main()

网络编程

  • 计算机网络:是多台独立自主的计算机形成的一个系统。
    连接起来的目的是计算机之间共享资源。
    使用TCP(能做到数据不传丢、流量控制、拥塞控制)/ICP连接起来的叫互联网。
#  创建一个无功能的服务器
from socket import socket, AF_INET, SOCK_STREAM
# SOCK_STREAM使用tcp,SOCK_DGRAM使用udp


def main():
    # 创建一个基于TCP协议的套接字对象
    # 因为我们做的是应用级的服务/产品,所以可以利用现有的传输服务来实现数据传输
    server = socket()  # AF_INET, SOCK_STREAM IPv4联网,只能这么写
    # 绑定IP地址(网络上主机的身份标识)和端口(用来区分不同服务的IP 地址的扩展,一个端口对应一个服务)(端口不是一个设备)
    server.bind(('10.7.189.75', 6543))  # ip写成localhost表示本地,6543表示端口号
    # 开始监听客户端的连接
    server.listen(512)  # 512表示队列大小
    print('服务器已经启动正在监听...')
    while True:
        # 通过accept方法接收客户端的连接
        # accept方法是一个阻塞式的方法,如果没有客户端连上来
        # 那么accept方法就会让代码阻塞,知道有客户端连接成功才返回
        # accept方法返回一个元组,元组中的第一个值代表客户端的对象
        # 元组中的第二个值又是一个元组,其中有客户端的IP地址和客户端的端口
        # client = server.accept()
        # print(client)
        client, addr = server.accept()
        print(addr, '连接成功.')
        client.send('hello789'.encode('utf-8'))
        client.close()


if __name__ == '__main__':
    main()

模拟一个聊天服务器

from socket import socket
from threading import Thread

# TCP - Transfer Control Protocol
# UDP - User Datagram Protocol


def main():
    class ClientHandler(Thread):

        def __init__(self, client):
            super().__init__()
            self._client = client

        def run(self):
            while True:
                try:
                    data = self._client.recv(1024)  # 返回的是二进制数据
                    for client in clients:
                        # if client != self._client  不给自己转发消息
                        client.send(data)  # 转发消息
                    if data.decode('utf-8') == 'byebye':
                        clients.remove(self._client)
                        self._client.close()  # 与说‘byebye’的客户端断开连接
                        break
                except Exception as e:  # 获取异常消息
                    print(e)  # 打印异常消息
                    clients.remove(self._client)  # 移除异常客户端
                    break

    server = socket()
    # 这里可以使用Python命令行参数 - sys.argv
    server.bind(('10.7.189.75', 54321))  # 端口号不要跟敏感号重复,建议取1025-65536区间
    # 开始监听
    server.listen(512)
    clients = []
    while True:
        # 接收用户请求
        client, addr = server.accept()
        clients.append(client)
        ClientHandler(client).start()


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/qq_41767930/article/details/79676390