Learn day8 re正则表达式\search函数\反射\tcp发送消息(循环)\udp发送消息
阅读原文时间:2023年07月12日阅读:2

1.匹配单个字符

# ### 正则表达式 - 单个字符匹配
import re
'''
findall 把匹配的结果直接返回到列表中
lst = re.findall("正则表达式","要匹配的字符串")
'''

预定义字符集

(1) \d 匹配数字

lst = re.findall("\d","UIUI uuiui898(*(* 神秘男孩xboy")
print(lst)

(2) \D 匹配非数字

lst = re.findall("\D","UIUI uuiui898(*(* 神秘男孩xboy")
print(lst)

(3) \w 匹配字母或数字或下划线 (正则函数中,支持中文的匹配)

lst = re.findall("\w","UIUI uui!@#$$%%^%^898(*(* 神秘男孩xboy")
print(lst)#['U', 'I', 'U', 'I', 'u', 'u', 'i', '8', '9', '8', '神', '秘', '男', '孩', 'x', 'b', 'o', 'y']

(4) \W 匹配非字母或数字或下划线

lst = re.findall("\W","UIUI uui!@#$$%%^%^898(*(* 神秘男孩xboy")
print(lst) #[' ', '!', '@', '#', '$', '$', '%', '%', '^', '%', '^', '(', '*', '(', '*', ' ']

(5)\s 匹配任意的空白符

lst = re.findall("\s","123 45 6")
print(lst)

(6) \S 匹配任意非空白符

lst = re.findall("\S","123 45 6")
print(lst) #['1', '2', '3', '4', '5', '6']

(7) \n 匹配一个换行符

strvar = """
本来无一物,何处惹尘埃, 无住 生心

"""
lst = re.findall("\n",strvar)
print(lst)

(8) \t 匹配制表符 缩进

lst = re.findall("\t","慎勿信汝意,汝意 不可信")
print(lst)

字符组 []

默认必须从字符组当中选一个

lst =re.findall("[abc]","6767yuyua-=-=")
print(lst)

print(re.findall('a[abc]b','aab abb acb adb'))

print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb'))

优化版 0-9 从0到9当中选一个 - 代表的是一个范围,是特殊字符

print(re.findall('a[0-9]b','a1b a2b a3b acb ayb'))

print(re.findall('a[abcdefg]b','a1b a2b a3b acb ayb adb'))

优化版 a-z 代表的是26个小写字母

print(re.findall('a[a-g]b','a1b a2b a3b acb ayb adb'))

print(re.findall('a[ABCDEFG]b','a1b a2b a3b aAb aDb aYb'))

优化版 A-Z 代表的是26个大写字母

print(re.findall('a[A-G]b','a1b a2b a3b aAb aDb aYb'))

print(re.findall('a[0-9a-zA-Z]b','a-b aab aAb aWb aqba1b'))

注意事项 : 0-z 不但能表示大小写字母,数字,还包含了一些特殊的字符

print(re.findall('[0-z]','='))

print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b'))

字符组中的 ^ 代表的是除了… [^-+*/] 除了-+*/之外的所有符号都匹配

print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd"))

如果就是想匹配特殊的符号,用\进行转义.

匹配^

print(re.findall('a[\^]b',"a^b"))

匹配\ \b 代表退格 backspace

lst = re.findall(r'a\\b',r'a\b')
print(lst) # 显示为 ['a\\b']
print(lst[0]) # 当拿出来打印时,会变成原有的样子

lst = re.findall(r'a[\\]b',r'a\b')
print(lst)
print(lst[0])

2.匹配多个字符

# ### 正则表达式 - 多个字符匹配
import re

### 量词练习

'''1) ? 匹配0个或者1个a '''
print(re.findall('a?b','abbzab abb aab'))

ab b ab ab b ab

'''2) + 匹配1个或者多个a '''
print(re.findall('a+b','b ab aaaaaab abb'))

ab aaaaaab ab

'''3) * 匹配0个或者多个a '''
print(re.findall('a*b','b ab aaaaaab abbbbbbb'))

b ab aaaaaab ab b b b b b b

'''4) {m,n} 匹配m个至n个a '''
print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb'))# aaab ab aab ab aab

{1} 必须只有1个

print(re.findall('a{1}b','aaab ab aab abbb aaz aabb'))# ab ab ab ab ab

{1,} 至少有1个

print(re.findall('a{1,}b','aaab ab aab abbb aaz aabb'))# aaab ab aab ab aab

### 贪婪匹配 和 非贪婪匹配

"""
贪婪匹配 : 默认向更多次匹配 (回溯算法)
非贪婪匹配: 默认向更少次匹配 (语法在量词的后面加?号)

. 代表除了\n,可以匹配任意字符
.? .+ .* .{m,n}

回溯算法:从左到右进行匹配,直到再也匹配不到了,回头,拿离右边最近的一个值.

非贪婪匹配语法: (语法在量词的后面加?号)
.?? .+? .*? .{m,n}?
"""

(1)贪婪匹配

strvar = "刘能和刘老根和刘铁棍子123子456"
lst = re.findall("刘.?",strvar)
print(lst) # 刘能 刘老 刘铁

lst = re.findall("刘.+",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子123子456']

lst = re.findall("刘.*",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子123子456']

lst = re.findall("刘.{1,100}",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子123子456']

(2)非贪婪匹配

strvar = "刘能和刘老根和刘铁棍子123子456"
lst = re.findall("刘.??",strvar)
print(lst) # ['刘', '刘', '刘']

lst = re.findall("刘.+?",strvar)
print(lst) # 刘能 刘老 刘铁

lst = re.findall("刘.*?",strvar)
print(lst) # ['刘', '刘', '刘']

lst = re.findall("刘.{1,100}?",strvar)
print(lst) # 刘能 刘老 刘铁

贪婪

lst = re.findall("刘.*子",strvar)
print(lst)

非贪婪

lst = re.findall("刘.*?子",strvar)
print(lst) #

### 边界符 \b ^ $

"""
卡住左边界:\bw
卡住右边界:d\b

任何的正则表达式,字符创左边都加上r,防止转义.
"""
strvar = "word pwd zef"
lst = re.findall(r"\bw.*",strvar)
print(lst)
lst = re.findall(r".*d\b",strvar)
print(lst)
lst = re.findall(r".*?d\b",strvar)
print(lst)
lst = re.findall(r"\bw.*?d\b",strvar)
print(lst)

单独匹配 word

lst = re.findall(r"\bw\S*",strvar)
print(lst)

"""
^ 必须以 .. 开头
$ 必须以 .. 结尾
无论是^ 还是 $ ,都需要把字符串看成一个整体;
"""
strvar = "大哥大嫂大爷"

print(re.findall('大.',strvar)) # ['大哥', '大嫂', '大爷']

print(re.findall('^大.',strvar)) #['大哥']

print(re.findall('大.$',strvar)) # ['大爷']

print(re.findall('^大.$',strvar)) # []

print(re.findall('^大.*?$',strvar)) # 大哥大嫂大爷

print(re.findall('^大.*?大$',strvar)) # 必须以大字开头,必须以爷字结尾,否则匹配不到;

print(re.findall('^大.*?爷$',strvar)) # ['大哥大嫂大爷']

print(re.findall('^g.*? ' , 'giveme 1gfive gay')) # giveme

print(re.findall('five$' , 'aassfive')) # ['five']

print(re.findall('^giveme$' , 'giveme')) #giveme

print(re.findall('^giveme$' , 'giveme giveme'))# []

print(re.findall('giveme' , 'giveme giveme')) #['giveme', 'giveme']

print(re.findall("^g.*e",'giveme 1gfive gay')) #giveme 1gfive

3.匹配分组_函数

# ### 分组匹配
import re
"""

1.正常分组 ()

1) 正常情况下用()圆括号进行分组 可以用\1 反向引用第一个圆括号匹配的内容。
2) (?:正则表达式) 表示取消优先显示的功能
"""

print(re.findall('.*?_good','wusir_good alex_good secret男_good'))
print(re.findall('(.*?)_good','wusir_good alex_good secret男_good'))

?: 取消优先显示括号的功能;

print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))

| 或 把长的字符串放到前面优先匹配,把短的容易匹配的放到后面;

strvar = "abcabcd"
lst = re.findall("abc|abcd",strvar)
print(lst)
lst = re.findall("abcd|abc",strvar)
print(lst)

匹配小数

strvar = "3.14 56 89.78 78sdfs"
lst = re.findall("\d+\.\d+",strvar)
print(lst)

匹配小数和整数

strvar = "3.14 56 89.78 78sdfs"
lst = re.findall("\d+\.\d+|\d+",strvar)
print(lst)

用分组匹配小数和整数

lst = re.findall("\d+(\.\d+)?",strvar)
print(lst)

不优先显示小括号内容

lst = re.findall("\d+(?:\.\d+)?",strvar)
print(lst)

匹配135或171的手机号

lst = re.findall("171[0-9]{8}|135\d{8}","17188886666 13566668888 13366668888")
print(lst)

加上^ 和 $ 意味着 只能写一组手机号,开头和结尾,不能是多个

lst = re.findall("^171[0-9]{8}$|^135\d{8}$","17188886666")
print(lst)

search 函数

"""
search 只匹配到一个就返回,返回的是对象
可以让分组的内容和正常匹配的结果同时显示;

想要拿到对象中的结果,使用group函数

findall 从左到右把所有符合条件的内容都返回到列表
不可以同时显示分组和正常匹配的结果
"""
obj = re.search("171[0-9]{8}|135\d{8}","17188886666 13566668888 13366668888")
print(obj)

obj.group() 用来获取该对象匹配到的值

res = obj.group()
print(res)

匹配www.baidu.com 或者 www.oldboy.com

strvar = "www.baidu.com www.oldboy.com"
obj = re.search("(www)\.(baidu|oldboy)\.(com)",strvar)

返回匹配的结果

res = obj.group()
print(res)

显示分组里面的内容

res = obj.group(1) # 显示第一个小括号里的内容
res = obj.group(2) # 显示第二个小括号里的内容
res = obj.group(3) # 显示第三个小括号里的内容

res = obj.group(4) # 显示第三个小括号里的内容 error

print(res)

一次性显示分组里所有内容 groups

res = obj.groups()
print(res)

用findall 来做 分组内容和正常匹配的内容2者之间不能同时显示,只能同一时间显示一个;

lst = re.findall("(?:www)\.(?:baidu|oldboy)\.(?:com)",strvar)
print(lst)

"5*6-7/3" 匹配 5*6 或者 7/3 search

strvar = "5*6-9/3" # 27
obj = re.search("\d+[*/]\d+",strvar)

返回匹配的结果

def calc(strvar):
if '*' in strvar:
num1,num2 = strvar.split('*')
return float(num1) * float(num2)

if '/' in strvar:  
    num1,num2 = strvar.split('/')  
    return float(num1) / float(num2)

res = obj.group()
print(res)
num = str(calc(res)) # 30.0

把最后得出的结果取代原来的5*6字符串

res2 = strvar.replace(res,num)
print(res2,type(res2)) #30.0-9/3

把剩下的字符串在匹配一遍即可

obj = re.search("\d+[*/]\d+",res2)
res3 = obj.group()
num = str(calc(res3))
print(num) # 3.0

把最后得出的结果取代原来的9/3字符串

res4 = res2.replace(res3,num)
print(res4,type(res)) #30.0-3.0

### 反向引用

strvar = "

大标题

"
obj = re.search("<.*?>.*?<.*?>",strvar)
print(obj.group()) #

大标题

obj = re.search("<(.*?)>.*?<(.*?)>",strvar)
print(obj.groups()) #('h1', '/h1')

反向引用 \1 表达把第一个括号里面的内容在使用一次;

print("<==========>")
strvar = "

大标题

"
obj = re.search(r"<(.*?)>.*?",strvar)
print(obj.groups()) #('h1', '/h1')

4.反射\魔术方法

# ### 类相关的魔术属性
class Human():
pass
class Man():
pass
class Woman():
pass

class Children(Man,Woman):
'''
成员属性: hair skin
成员方法: cry eat __drink
功能:描述小孩的特征
'''
hair = "black"
skin = "yellow"

# 绑定方法  
def cry(self):  
    print("小孩会哭")

# 普通方法  
def eat():  
    print("小孩下生会吃饼干")

def smile(self,func):  
    # \_\_name\_\_  获取函数名  
    res = func.\_\_name\_\_  
    print(res) #ceshi  
# 私有方法  
def \_\_drink(self):  
    print("小孩喜欢喝奶奶")

obj = Children()
obj.abc = 10

__dict__ 获取对象或类的内部成员结构

print(obj.__dict__)
print(Children.__dict__)

__doc__ 获取对象或类的内部文档

print(Children.__doc__)
print(obj.__doc__)

__name__ 获取类名函数名

def ceshi():
print(123)
obj.smile(ceshi)

__class__ 获取当前对象所属的类

print(obj.__class__)

__bases__ 获取一个类直接继承的所有父类,返回元组

res = Children.__bases__
print(res) # (, )

### 反射

"""

概念:通过字符串去操作类对象 或者 模块中的 属性方法

"""

(1)hasattr() 检测对象/类是否有指定的成员

res = hasattr(obj,"hair")
res = hasattr(obj,"cry")
print(res) # True
res = hasattr(Children,"hair")
res = hasattr(Children,"eat123")
print(res)

(2)getattr() 获取对象/类成员的值

res = getattr(obj,"hair")
func = getattr(obj,"cry")
print(res)
func() #小孩会哭

res = getattr(Children,"skin")
print(res)
func = getattr(Children,"eat")
func()

"""
def cry(self):
print("小孩会哭")
如果通过对象反射出来的绑定方法,里面的self 这个参数自动传递
如果通过类 反射出来的方法,里面的self 这个参数手动传递
"""
print("<==start==>")

通过对象反射的

func = getattr(obj,"cry") # self 系统自动传递
func()

通过类反射的

func = getattr(Children,"cry")
func(13213213131212) # 让形参实参保持一致,self需要手动传递
print("<==end==>")

综合案例

'''
res = input("请用户输入要调用的方法")
if hasattr(Children,res):
func = getattr(Children,res)
func()
'''

(3)setattr() 设置对象/类成员的值

setattr(obj,"eye","蓝色的眼睛")
print(obj.eye)
setattr(Children,"ceshi111",lambda : print("ceshi111"))
Children.ceshi111()

"""

一般在类外创建的都是静态方法,无论是对象还是类都可以调用

在类外创建绑定方法的过程

import types
types.MethodType(函数,obj)
"""

(4)delattr() 删除对象/类成员的值

delattr(obj,"eye")

obj.eye

delattr(Children,"ceshi111")

Children.ceshi111()

### 关于模块的反射

import sys

sys.modules 返回一个字典,这个字典存放的都是系统的模块

print(sys.modules)
"""
{'builtins': ,
'sys': ,
'_frozen_importlib': ,
'_imp': ,
'_warnings': , '_thread': , '_weakref': , '_frozen_importlib_external': , '_io': , 'marshal': , 'nt': , 'winreg': , 'zipimport': , 'encodings': , 'codecs': , '_codecs': , 'encodings.aliases': , 'encodings.utf_8': , '_signal': ,
'__main__': ,
'encodings.latin_1': , 'io': , 'abc': , '_weakrefset': , 'site': , 'os': , 'errno': , 'stat': , '_stat': , 'ntpath': , 'genericpath': , 'os.path': , '_collections_abc': , '_sitebuiltins': , '_bootlocale': , '_locale': , 'encodings.gbk': , '_codecs_cn': , '_multibytecodec': , 'sysconfig': , 'encodings.cp437': ,
'sitecustomize': }
"""

通过__main__ 字典的键,直接获取的是当前的模块对象 mymodule4

mod = sys.modules['__main__'] #

def func1():
print("这是func1方法")
def func2():
print("这是func2方法")
def func3():
print("这是func3方法")

通过用户输入,不停的反射模块当中的方法.

while True:
res = input("请选择要调用的函数")
# 判断是否存在当前方法
if hasattr(mod,res):
# 通过字符串反射该方法
func = getattr(mod,res)
func()
else:
print("没有当前方法")

5.tcp发送消息

tcp三次握手过程

tcp四次挥手过程

网络中包的传输过程

socket所在位置

[server端] # ### 服务端
import socket

1.创建一个socket对象 , 默认按照tcp协议创建

sk = socket.socket()

2.绑定ip 和 端口 (在网络上注册该主机,让其他主机找到你)

'''bind( 元组 ) 默认本地ip 127.0.0.1 (ip,端口) '''
sk.bind( ("127.0.0.1",9000) )

3.开启监听

sk.listen()

4.三次握手

'''conn 是三次握手后的连接对象,addr是对方的ip和端口号'''
conn,addr = sk.accept()

print(conn)

('127.0.0.1', 51123)

print(addr)

5.写收发数据的逻辑

"""
1kb = 1024B
1024kb = 1024 * 1024B
1mb = 1100000000
一发一收是一对,发和收要一一匹配
recv(字节)
"""

接收数据 recv后面的字节数,是一次性最大接收这么多个字节;

msg = conn.recv(1024)
print(msg.decode("utf-8"))

发送数据

conn.send("你是个好人..".encode())

6.四次挥手

conn.close()

7.退还端口

sk.close()

**[client端]
**

# ### 客户端
import socket
# 创建tcp对象
sk = socket.socket()
# 直接与服务器主机建立连接
'''connect( 元组 ) (ip,端口号)'''
sk.connect( ("127.0.0.1" , 9000) )

# send 用来发送消息,recv 用来接收消息
'''send(二进制字节流)'''
sk.send("我爱你".encode("utf-8"))

# 接收数据
# res = sk.recv(1024)
# print(res.decode())

# 关闭连接
sk.close()

6.tcp循环发送消息

[server端] # ### 服务端
import socket

1.创建一个socket对象 , 默认按照tcp协议创建

sk = socket.socket()

2.绑定ip 和 端口 (在网络上注册该主机,让其他主机找到你)

'''bind( 元组 ) 默认本地ip 127.0.0.1 (ip,端口) '''
sk.bind( ("127.0.0.1",9000) )

3.开启监听

sk.listen()

listen accept recv 都是阻塞;如果不满足条件,程序不会往下执行;

5.收发数据 quit

while True:
# 4.三次握手
'''conn 是三次握手后的连接对象,addr是对方的ip和端口号'''
conn,addr = sk.accept()
while True:
# 收消息
msg = conn.recv(1024)
print(msg.decode())
# 发消息
message = input("老弟,要发什么?>>>")
conn.send(message.encode("utf-8"))
if message == "q":
break

6.四次挥手

conn.close()

7.退还端口

sk.close()

[client端] # ### 客户端
import socket

创建tcp对象

sk = socket.socket()

直接与服务器主机建立连接

'''connect( 元组 ) (ip,端口号)'''
sk.connect( ("127.0.0.1" , 9000) )

while True:
# 发消息
message = input(">>>:")
sk.send(message.encode("utf-8"))
# 收消息
res = sk.recv(1024)
if res == b'q':
break
print(res.decode("utf-8"))

关闭连接

sk.close()

7.udp发送消息

[server端] # ### 服务端
""" 如果是udp的服务端 ,只能先接收数据 ,tcp服务端可以先发也可以先收 """
import socket

1.创建udp对象 type = SOCK_DGRAM 代表udp协议

sk = socket.socket(type=socket.SOCK_DGRAM)

2.绑定ip和端口 (在网络中注册该主机)

sk.bind( ("127.0.0.1",9000) )

3.udp服务器,第一次启动时,一定是先接收数据,在发送数据

msg,cli_addr = sk.recvfrom(1024)
print(msg.decode("utf-8"))
print(cli_addr)

4.关闭udp连接

sk.close()

[client端] # ### 客户端
import socket

1.创建udp对象 type = SOCK_DGRAM 代表udp协议

sk = socket.socket(type=socket.SOCK_DGRAM)

2.sendto(要发的消息,(ip,端口号))

sk.sendto( "你好".encode("utf-8") , ("127.0.0.1",9000) )

3.关闭udp连接

sk.close()

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章