Python第四周学习总结


面向对象继承

多重继承

如果一个类有多个父类, 而多个父类又有公共的父类(菱形继承, 钻石继承)
那么在搜索属性和方法时搜索的一局是C3算方法(有点类似于广度优先搜索)
这个是Python中的一个改进, 在此之前搜索的算法是深度优先算法

class A(object):

    def foo(self):
        print('A\'s foo')


class B(A):

    def foo(self):
        print('B\'s foo')


class C(A):

    def foo(self):
        print('C\'s foo')


class D(B, C):

    def foo(self):
        pass

尽量让后两个父类设定为抽象类, 在子类中实现方法

class Father(object):
    def __init__(self, name):
        self._name = name

    def drink(self):
        print(self._name, 'is drinking')

    def gamble(self):
        print(self._name, 'is gamble')


class Monk(object, metaclass=ABCMeta):

    @abstractmethod
    def eat_vegetable(self):
        pass

    @abstractmethod
    def chant(self):
        pass


class Musician(object, metaclass=ABCMeta):

    @abstractmethod
    def play_piano(self):
        pass

    @abstractmethod
    def drink(self):
        pass

class Son(Father, Monk, Musician):
    def __init__(self, name, nickname, art_name):
        # 给类传参数需要传self
        Father.__init__(self, name)
        self._nickname = nickname
        self._art_name = art_name

    def eat_vegetable(self):
        print(self._nickname, 'is eating vegetable')

    def chant(self):
        print(self._nickname, 'is chanting')

    def play_piano(self):
        print(self._art_name, 'is playing piano')

    def drink(self):
        print('master', self._art_name, 'is drinking')

正则表达式

基本符号

符号解释示例说明
匹配任意字符b.t示例可以匹配bat / but / b#t / b1t等
\w匹配字母/数字/下划线b\wt可以匹配bat / b1t / b_t等 但不能匹配b#t
\s匹配空白字符(包括\r、\n、\t等)love\syou可以匹配love you
\d匹配数字\d\d可以匹配01 / 23 / 99等
\b匹配单词的边界\bThe\b
^匹配字符串的开始^The可以匹配The开头的字符串
匹配字符串的结束.exe可以匹配.exe结尾的字符串
\W匹配非字母/数字/下划线b\Wt可以匹配b#t / b@t等,但不能匹配but / b1t / b_t等
\S匹配非空白字符love\Syou可以匹配love#you等,但不能匹配love you
\D匹配非数字\d\D可以匹配9a / 3# / 0F等
\B匹配非单词边界\Bio\B
[]匹配来自字符集的任意单一字符[aeiou]可以匹配任一元音字母字符
[^]匹配不在字符集中的任意单一字符[^aeiou]可以匹配任一非元音字母字符
*匹配0次或多次\w*
+匹配1次或多次\w+
?匹配0次或1次\w?
{N}匹配N次\w{3}
{M,}匹配至少M次\w{3,}
{M,N}匹配至少M次至多N次\w{3,6}
/分支foo/
(?#)注释
(exp)匹配exp并捕获到自动命名的组中
(?exp)匹配exp并捕获到名为name的组中
(?:exp)匹配exp但是不捕获匹配的文本
(?=exp)匹配exp前面的位置\b\w+(?=ing)\b\w+(?=ing)
(?<=exp)匹配exp后面的位置(?<=\bdanc)\w+\b可以匹配I love dancing and reading中的第一个ing
(?!exp)匹配前面不是exp的位置
(?匹配前面不是exp的位置
*?重复任意次,但尽可能少重复重复任意次,但尽可能少重复将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串
+?重复1次或多次,但尽可能少重复
??重复1次或多次,但尽可能少重复
{M,N}?重复M到N次,但尽可能少重复
{M,}?重复M次以上,但尽可能少重复

re模块核心函数

函数说明
compile(pattern, flags=0)编译正则表达式返回正则表达式对象
match(pattern, string, flags=0)用正则表达式匹配字符串 成功返回匹配对象 否则返回None
search(pattern, string, flags=0)搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None
split(pattern, string, maxsplit=0, flags=0)用正则表达式指定的模式分隔符拆分字符串 返回列表
sub(pattern, repl, string, count=0, flags=0)用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数
fullmatch(pattern, string, flags=0)match函数的完全匹配(从字符串开头到结尾)版本
findall(pattern, string, flags=0)查找字符串所有与正则表达式匹配的模式 返回字符串的列表
finditer(pattern, string, flags=0)查找字符串所有与正则表达式匹配的模式 返回一个迭代器
purge()清除隐式编译的正则表达式的缓存
re.I / re.IGNORECASE忽略大小写匹配标记
re.M / re.MULTILINE多行匹配标记

例子

main():
    qq = input('QQ:')
    username = input('username:')
    phone_num = input('phonenumber:')
    # 提前准备正则表达式
    pattern1 = re.compile(r'^[0-9a-zA-Z_]{6,20}$')
    if re.match(r'^[1-9]\d{4,11}$', qq):
        print(re.match(r'^[1-9]\d{4,11}$', qq))
        print('QQ success')
    else:
        print('QQ error')
    if pattern1.match(username):
        print(pattern1.groups)
        print(pattern1.match(username))
        print('username success')
    else:
        print('username error')
    pattern2 = (re.match(r'^1[38][0-9]\d{8}$', phone_num)) or 
    (re.match(r'^1[45][0-35-9]\d{8}$', phone_num)) or (re.match(r'^17[6-8]\d{8}$', phone_num))
    if pattern2:
        print('phone_number success')
    else:
        print('phone_number error')
def main():
    my_username = input('UserName:')
    # 从头匹配
    juct1 = re.match(r'\w{6,20}', my_username)
    # 从中间匹配
    juct2 = re.search(r'\w{6,20}', my_username)
    # 完整匹配
    juct3 = re.search(r'^\w{6,20}$', my_username)
    if juct1:
        print(re.match(r'\w{6,20}', my_username))
        print(juct1.span())
        print(juct1.group())
        print('success')
    else:
        print(re.match(r'\w{6,20}', my_username))
        print('error')

进程与线程

进程

进程是操作系统的分配内存的基本单位,进程之间的内存是相互隔离的
如果进程之间想要通信就要通过IPC机制和socket套接字。
进程可以划分为线程, 线程是进程的执行单元,也是操作系统分配cpu的基本单元
如果一个任务执行时间很长,就将程序分为多个线程,提升执行效率,缩短程序的执行时间
让用户获得更好的用户体验
process 进程

常用方法

创建线程的两种方式
直接创建Thread对象, 并通过target参数指定线程启动后要执行的任务
通过继承Thread自定义线程类重写run方法指定线程启动后执行的任务

方法解释
p.daemon = True守护进程,守护进程不可以再有子进程,并且主进程死守护进程就死,要写在p.start()之前
p.join()主进程等子进程执行完 之后再结束—> 等的时间就是执行时间最长的子进程执行的时间
p.terminate()-强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,用该方法需要特别小心这种情况。如果p保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive()如果p仍然运行,返回True
p.name查看进程的名称
p.pid查看进程的pid

关于lock的用法

def deposit(self, money):
    # 但多个线程同时访问一个资源的时候,就有可能因为竞争资源导致资源的状态错误
    # 被多个线程访问的资源我们通常称之为临界资源,对临界资源的访问需要加以保护
    if money > 0:
        # 抢到锁的线程进行对资源的操作
        self._lock.acquire()
        try:
            new_balance = self._balance + money
            time.sleep(0.01)
            self._balance = new_balance
        finally:
            self._lock.release()

线程

创建线程的两种方式
直接创建Thread对象, 并通过target参数指定线程启动后要执行的任务
通过继承Thread自定义线程类重写run方法指定线程启动后执行的任务
如果多个任务之间没有任何关联(独立子任务)而且希望能利用CPU的多核特性
那么我们推荐使用多进程

常用方法

函数说明
isAlive()返回线程是否在运行。正在运行指启动后、终止前
get/setName(name)获取/设置线程名
start()线程准备就绪,等待CPU调度
is/setDaemon(bool)获取/设置是后台线程(默认前台线程(False)):如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止。如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
start():启动线程
join([timeout])阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)

自定义线程子类

创建线程的两种方式
直接创建Thread对象, 并通过target参数指定线程启动后要执行的任务
通过继承Thread自定义线程类重写run方法指定线程启动后执行的任务

class My_thread(Thread):
    def __init__(self, str1, count):
        super().__init__()
        self._str1 = str1
        self._count = count


    def run(self):
        for _ in range(self._count):
            print(self._str1, end=' ', flush=True)

socket

通过socket进行网路数据的传输

TCP

TCP提供一种面向连接的、可靠的字节流服务。面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP

server端

def main():
    # 创建一个基于TCP的套接字对象
    # 因为我们做的可能是一个应用级的产品或服务,所以可以利用一个现有的传输服务来实现数据传输
    server = socket(AF_INET, SOCK_STREAM)
    # 绑定IP地址 端口号:用来区分同一个地址不同的服务 0-65535
    # 端口HTTP-80 HTTPS-443 SMTP-25 POP3-110 选择端口避开1024前
    server.bind(('10.7.189.82', 2048))
    # server.bind(('localhost', 2048))
    # server.bind(('127.0.0.1', 2048))
    # 监听 参数:队列大小(合适就好)
    server.listen(512)
    print('server start listen...')
    # netstat -na查看正在执行服务端口
    while True:
        # 通过accept方法接收客户端的连接
        # accept方法是一个阻塞式的方式 如果没有客户端连接
        # 那么accept方法就会让代码阻塞,直到客户端连接才返回
        # accept方法返回一个元组,元组中的第一个值代表的是客户端对象
        # 元组中的第二个值又是一个元组, 其中有客户端的IP地址和客户端的端口
        # telnet ip 端口 连接服务器
        client, addr = server.accept()
        curr_time = datetime.datetime.now()
        client.send(curr_time.__str__().encode('utf-8'))
        print(addr, 'connect success')
    socket.close()

client端

    client = socket()
    client.connect(('10.7.189.82', 2048))
    my_time = client.recv(1024)
    print(type(my_time))
    print(my_time.decode('utf-8'))

UDP

在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和QQ就是使用的UDP协议。

通过UDP传输图片例子

发送端

from socket import socket, SOCK_DGRAM
import time


def main():
    sender = socket(type=SOCK_DGRAM)
    with open('6597532661052146017.jpg', 'rb') as img:
        data = img.read()
        data_len = len(data)
        total = 0
        while total < data_len:
            sender.sendto(data[total:total+1024],
                          (('10.7.189.82', 9876)))
            total += 1024
            time.sleep(0.001)
        print('over')

接收端

from socket import socket, SOCK_DGRAM
import time


def main():from socket import socket, SOCK_DGRAM


def main():
    reciver = socket(type=SOCK_DGRAM)
    reciver.bind(('10.7.189.82', 9876))
    data = bytes()
    while True:
        seg, addr = reciver.recvfrom(1024)
        data += seg
        if len(data) == 174355:
            break
    with open('hello.jpg', 'wb')as f:
        f.write(data)
        print('图片已接收')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值