8. re正则表达式\search函数\反射\tcp发送消息(循环)\udp发送消息

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 <class 'str'>

# 把剩下的字符串在匹配一遍即可
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 <class 'str'>


# ### 反向引用
strvar = "<h1>大标题</h1>"
obj = re.search("<.*?>.*?<.*?>",strvar)
print(obj.group()) #<h1>大标题</h1>

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

# 反向引用  \1  表达把第一个括号里面的内容在使用一次;
print("<==========>")
strvar = "<h1>大标题</h1>"
obj = re.search(r"<(.*?)>.*?</(\1)>",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) # (<class '__main__.Man'>, <class '__main__.Woman'>)

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

# (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': <module 'builtins' (built-in)>, 
'sys': <module 'sys' (built-in)>, 
'_frozen_importlib': <module '_frozen_importlib' (frozen)>, 
'_imp': <module '_imp' (built-in)>, 
'_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\\Program Files\\Python36\\lib\\encodings\\__init__.py'>, 'codecs': <module 'codecs' from 'C:\\Program Files\\Python36\\lib\\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Program Files\\Python36\\lib\\encodings\\aliases.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Program Files\\Python36\\lib\\encodings\\utf_8.py'>, '_signal': <module '_signal' (built-in)>, 
'__main__': <module '__main__' from 'D:/周末四期/L008/mymodule4.py'>, 
'encodings.latin_1': <module 'encodings.latin_1' from 'C:\\Program Files\\Python36\\lib\\encodings\\latin_1.py'>, 'io': <module 'io' from 'C:\\Program Files\\Python36\\lib\\io.py'>, 'abc': <module 'abc' from 'C:\\Program Files\\Python36\\lib\\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\\Program Files\\Python36\\lib\\_weakrefset.py'>, 'site': <module 'site' from 'C:\\Program Files\\Python36\\lib\\site.py'>, 'os': <module 'os' from 'C:\\Program Files\\Python36\\lib\\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\\Program Files\\Python36\\lib\\stat.py'>, '_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\\Program Files\\Python36\\lib\\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\\Program Files\\Python36\\lib\\genericpath.py'>, 'os.path': <module 'ntpath' from 'C:\\Program Files\\Python36\\lib\\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Program Files\\Python36\\lib\\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\\Program Files\\Python36\\lib\\_sitebuiltins.py'>, '_bootlocale': <module '_bootlocale' from 'C:\\Program Files\\Python36\\lib\\_bootlocale.py'>, '_locale': <module '_locale' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'C:\\Program Files\\Python36\\lib\\encodings\\gbk.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'sysconfig': <module 'sysconfig' from 'C:\\Program Files\\Python36\\lib\\sysconfig.py'>, 'encodings.cp437': <module 'encodings.cp437' from 'C:\\Program Files\\Python36\\lib\\encodings\\cp437.py'>, 
'sitecustomize': <module 'sitecustomize' from 'C:\\Program Files\\JetBrains\\PyCharm 2019.1.3\\helpers\\pycharm_matplotlib_backend\\sitecustomize.py'>}
"""

# 通过__main__ 字典的键,直接获取的是当前的模块对象 mymodule4
mod = sys.modules['__main__'] #<module '__main__' from 'D:/周末四期/L008/mymodule4.py'>

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()

# <socket.socket fd=476, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 51123)>
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()

 

posted @ 2019-08-17 14:21  善战者求之于势  阅读(277)  评论(0编辑  收藏  举报