码迷,mamicode.com
首页 > 其他好文 > 详细

面向对象_正则

时间:2020-10-06 21:00:04      阅读:24      评论:0      收藏:0      [点我收藏+]

标签:显示   添加   UNC   length   实例   raise   utf-8   __new__   反向   

# ###

"""面向对象"""
# ### self的意思就是当前类的(实例化)对象,cls的意思就是当前类

# (1)调用类中的属性或方法,对象obj.属性,obj.方法; 类(不带括号).属性,类.方法
    类中方法括号里加了self,适合用对象调用(自动传参obj),如果用类调用就得在类的括号里加obj,类.func(obj)
    类中方法括号里没有self,适合用类调用,类.func(),如果用对象调用就得将方法和对象绑定
    在类当中调用类本身的属性或方法只能用 类.成员(能用类.成员吗) 或 self.成员

    给类添加属性或方法,类.属性=xx  类.func=func(这个func自定义)
    给对象添加属性或方法,对象.属性=xx  对象.func=func(这个func自定义)

    类的命名一般用驼峰命名法

# MethodType 把自定义的方法绑定到对象上,  types.MethodType(方法名,obj),再调用时用obj.方法名(不用传参obj)
    """import types"""
# __dict__ 查看类或对象的成员,类.__dict__ 或 obj.__dict__
# _类名__私有成员名 利用改名策略调用私有成员(不推荐)
    可通过在类中定义一个公有绑定方法,调用自己的私有成员,然后再在类外调用这个公有绑定方法

# object 是所有类的父类
# supper 本身是一个类,>>> supper()是一个对象,用于调用且只能调用父类的绑定方法
    super().__init__() #必须继承父类的__init__构造方法
    """self 与 super 的区别"""
    self  在调用父类成员时,如果自己本类含有该成员,调用自己的,否则调用父类的
    super 永远只调用父类成员,不调用自己本类的
# mro列表:方法调用顺序列表 语法: 类.mro() 使用C3算法计算,返回一个列表 super() 就是按照这个列表的顺序,依次进行调用
# issubclass 判断是否是子父关系,和isinstance用法相似
    类的成员属性和对象的成员属性不一样,存储在不同的内存空间

"""魔术方法:特定时机自动触发"""
# __init__ 构造方法,实例化对象时触发,能为对象添加新成员,参数self
# __new__魔术方法,实例化对象时触发(触发时机在__init__之前),用来控制对象的创建过程,
    参数(至少一个cls接收当前的类),通常返回对象或None
    """注意:__new__和__init__的参数要保持一致,除了一个是cls一个是self"""
    如果__new__返回的不是自己本类的对象,不会触发构造方法__init__
    class MyClass():
        def __new__(cls):
            print(cls)  #<class ‘__main__.MyClass‘>
            #借助父类objec,里面的__new__魔术方法创建对象
            # 1 返回本对象
            # return object.__new__(cls)
            # return obj  错误写法
            # 2 返回其他类的对象
            return obj2 #你实例化对象是别人的对象,然后对象.成员是别人的成员,别人没这个成员就报错
            # 3 不返回任何对象
            # return None #这样你实例化对象也相当于没这个对象,不能用对象了

"""单态模式(单例模式):无论实例化对象多少次,都有且只有一个对象"""为了节省空间,加快效率,提出单态模式
    (1)基本语法
    class Singleton():
        __obj = None
        def __new__(cls):
            if cls.obj is None:
                cls.obj = object.__new__(cls)
            return cls.__obj

# __del__ 析构方法,当对象被内存收回时触发(1) 页面执行完毕回收所有变量,
    (2) 指向对象的变量名(obj1啊,obj2啊)都被删除),参数self,无返回值
# __call__魔术方法,把对象当作函数调用时触发,即obj()触发,用作模拟函数化操作,参数至少一个self,返回值看需求
# __str__魔术方法,用print(obj)或者str(obj)时触发,用来查看对象,参数self,必须返回字符串类型
# __repr__魔术方法,用repr(obj)时触发,用来查看对象,必须返回字符串类型 
    在系统底层默认加了 __str__=__repr__ ,所以用str(对象)的时候也可以触发
# __bool__魔术方法,用bool(对象)时触发,用来强转对象,参数self,必须返回bool型
# __add__魔术方法(与之相关的__radd__反向加法),obj+xx时触发__add__; xx+obj时触发__radd__,obj1+obj2时先触发__add__
# __len__魔术方法,用len(obj)时触发,用来检测对象或类中成员个数,参数self,必须返回整型
def __len__(self):
    return len([i for i in dictvar if not (i.startswith("__") and i.endswith("__"))])

<<<<<<<<<<<<<<<<重要知识点>>>>>>>>>>>>>>
    """见证奇迹: 1实例化对象并传参; 2将这个对象obj写入文档; 3运行完代码后关闭程序;
     4打开代码把之前的实例化和写入文档注释掉,添加从文档中读取对象obj,
    然后这个上次存入文档的对象还可以点出原来类MyClass以及对象的方法和属性
    也就是说,在MyClass类不变的前提下把对象存进文档再拿出来他还是以前那个对象,
    可以大大简化数据存储(以前要存多个变量,现在只用存一个对象就行了)"""
    import pickle
    class MyClass():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def func(self):
            print("见证奇迹的时刻!")

    # obj=MyClass("狗子",10)
    # with open("test1.txt",mode="wb") as fp:
        # pickle.dump(obj,fp)
    with open("test1.txt",mode="rb") as fp:
        obj=pickle.load(fp)
    print(obj)
    print(obj.name)
    obj.func()

"""闭包函数""" 内函数调引外函数的变量称为闭包
def func():
    name = python
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()  # f = func() = inner 
f()  # f() = inner 
# 输出结果:python

"""装饰器""" # 是一种特殊的闭包函数
# 这里内函数就是引用了外函数的传参func,也称为闭包
定义:装饰用于拓展原来函数功能的一种语法,返回新函数替换旧函数
优点:在不更改原函数代码的前提下,给函数拓展新的功能
语法:@
###1 装饰器的原型
def kuozhan(func):
    def newfunc():
        print("厕所前蓬头垢面")
        func()
        print("厕所后容光焕发")
    return newfunc
def func():
    print("我是高富帅")
func=kuozhan(func) #func=newfunc
func() #调用newfunc

# ###2 装饰器@符语法
#下面是基于python2.7的语法
# coding=utf-8
def func1(t_func):
    print "执行func1函数"
    print "打印传参的函数名", t_func.__name__
    return "返回值"

# func2=func1(func2) 也就相当于执行了func1函数传参func2,然后把结果赋值给func2了
@func1
def func2():
    print "执行func2函数"

print func2,type(func2)
"""
# 执行结果:
执行func1函数
打印传参的函数名 func2
返回值 <type ‘str‘>
"""


# self代表类的对象,一般用obj表示,传进去的也是这个对象
# cls代表类,一般在类中为别的类添加成员,需要带参数cls,然后cls.方法,cls.属性

"""类中的方法:"""
    无参的普通方法 : 只能用类调用
    (1)绑定到对象(参数有self就是绑定到对象): 在调用当前方法时,自动传递self对象参数
    (2)@classmethod 绑定到类(参数有cls): 在调用当前方法时,自动传递cls这个类参数
    (3)@staticmethod 静态方法(一般没self,但可以有其他参数): 无论是对象还是类都
        可以调用,把方法作为普通方法进行使用,有几个参数就传递几个参数

# property
    把方法变成属性:用来控制成员的 获取 , 设置 , 删除
    # 写法一
    # @property下面跟(修饰)一个方法A  给一个方法添加property标志
    # @方法A.setter下面跟一个方法B  设置这个property标志的方法A时,触发方法B #设置就是指更改
    # @方法A.deleter下面跟一个方法C  删除这个property标志的方法A时,触发方法C
    
    # 写法二 先在类中定义def get_A(self) def set_A(self) def del_A(self)
    # 然后在类中写一行 username = property(get_A,set_A,del_A)
    必须按照这个顺序进行传递:(获取方法 , 设置方法 , 删除方法),且只能传这3个参数

"""正则表达式"""
    import re
# re.findall 匹配所有内容,缺陷:不能把匹配到的内容和分组里面的内容同时显示出来,返回的是列表
    lst = re.findall(正则表达式,字符串)
# ###(1) 预定义字符集
# \d 匹配数字
# \D 匹配非数字
# \w 匹配字母或数字或下划线     (正则函数中,支持中文的匹配)
# \W 匹配非字母或数字或下划线
# \s 匹配任意的空白符 \n \t \r " "
# \S 匹配任意非空白符
# \n 匹配一个换行符 [最好在正则表达式的前面加上r,让转义字符失效,原型化匹配]
# \t 匹配一个制表符

# ### (2) 字符组 从小组中默认选一个
# [123]从1,2,3中任选一个
# 0-9 0到9  -是特殊字符 , 具有特殊含义
# ^ 出现在字符组中,代表除了xx以外
# 匹配特殊符号 利用\ 让原来有意义的字符失效, 通过转义来实现匹配
# 匹配\ 用\\

# ###(1) 量词基本语法
# . 匹配除换行符以外的所有字符
# ? 匹配0个或者1个a 
# + 匹配1个或者多个a 
# * 匹配0个或者多个a
# {m,n} 匹配m个至n个a,n可以取到
# {m,} 至少m次
# {m}  必须是m次

# ###(2)贪婪模式与非贪婪模式
    贪婪模式:默认向更多次匹配, 非贪婪模式:默认向更少次匹配,在普通的匹配后面加 ? 
    如.?? .+? .*? .{1,25}?

# ###(3) 边界符 
# \bw 卡住左边界(就是匹配以\bw右边字符为开头的字符)
# d\b 卡住右边界(就是匹配以d\b左边字符为结尾的字符)
# ^ 整个字符串必须以...开头
# $ 整个字符串必须以...结尾
    如果正则表达式里面出现了^ $ ,代表把这个字符串看成一个整体,再去匹配

# ###匹配分组
# (xxx) 把想要匹配的内容,用小圆括号包起来,表达分组,并且优先显示括号内的东西(优先显示就是只显示它)
# (?:xxx) ?: 取消括号优先显示的功能
# | 代表或 , a|b 匹配字符a 或者 匹配字符b . 把用来匹配长字符串的写在前面,
    用来匹配短字符串的写在后面,不然会匹配不到那个长的字符串
# \ 可以把有意义的字符变得无意义,还可以把无意义的字符变得有意义,用来转义字符
# r"\d+\.\d+|\d+"匹配小数和整数,优化写法 r"\d+(?:\.\d+)?"

# search 匹配到一个内容就直接返回,优点:可以把分组的内容,和实际匹配到的内容分开,同时显示,返回的是对象obj
# obj.group()  获取匹配到的内容,返回字符串
# obj.groups() 获取分组里面所有的内容,返回元组

# ###命名分组
# \1 反向引用,代表的是把第一个括号匹配到的值,拿过来在引用一次r"<(.*?)>(.*?)<(/\1)>"
# (?P<组名>正则表达式) 给这个组起一个名字 (?P=组名) 引用之前组的名字,把该组名匹配到的内容放到当前位置
    "<p>今天天气不错</p>" lst = re.findall(r"<(?P<tag1>.*?)>(.*?)</(?P=tag1)>",strvar)

"""正则函数"""
# match 验证用户输入内容 search在正则表达式的前面加上^ 就与match函数一模一样
# re.split 语法 re.split("正则表达式",字符串,分割的次数-可选) 按正则表达式选出的字符串分割,返回列表?
# sub 替换 返回的结果是一个字符串re.sub(r"[|&-]","%",strvar)
"""注意,如果正则表达式里面带括号,sub不会只替换括号里的内容,所以需要把除括号以外的字符串都加上
例如a=re.sub("下载(.*?)漫(.*?)的","678",b)会直接把 下载(.*?)漫(.*?)的 这一段替换成678
所以要用a=re.sub("下载(.*?)漫(.*?)的","下载"+"678"+"漫画里的",b)
"""
# subn 替换 用法上与sub一样,但是返回的结果是元组(替换后的结果,替换的次数)
# finditer 匹配字符串中相应内容,返回迭代器(装着对象的迭代器)
    findall 与 finditer用法一样,区别在于 findall返回的是列表,finditer返回迭代器
# compile 指定一个统一的匹配规则,用compile 编译一个正则表达式,终身受益,不用对同一个正则反复编译啦
    pattern = re.compile("\d")编译;  res = pattern.findall(strvar)使用

# ### 修饰符
# re.I 使匹配对大小写不敏感 ("<h1>(.*?)</h1>",字符串,flags=re.I)
# re.M 使每一行都能够单独匹配(多行匹配),影响 ^ 和 $ ,就是把每一行都当成一个字符串取匹配
# re.S 使 . 匹配包括换行在内的所有字符(有换行的话匹配出来还有\n)
# flags=re.I|re.S 使用多个修饰符的写法 (拓展) #修饰符之间用|分割


"""与类相关的魔术属性"""
# __doc__  获取对象或类的内部文档 用法 对象/类.__doc__
# __name__ 获取类名函数名
# __class__ 获取当前对象所属的类
# __bases__ 获取一个类直接继承的所有父类,返回元组

"""类中的反射"""
    通过对象名/类名/文件名(都是字符串) 获取对应对象/类/文件中的成员
# hasattr() 检测对象/类中是否有指定的成员 hasattr(obj,"eat") 记法(has attribute),返回Ture/False
# getattr() 获取对象/类成员的值 获取属性就返回值,获取方法就返回函数,这个函数可以直接调用
    res = getattr(obj,"eye") print(res)通过对象把属性返回出来
    func = getattr(obj,"eat")对象反射调用func(); func = getattr(Children,"eat")类反射调用func()
    """新用法:getattr可以从模块里获取模块中的类或者模块中的函数,getattr(模块,类名或函数名),返回类或函数"""
# ###通过对象把方法反射出来,是绑定方法 #绑定方法调用不用传参,通过类把方法反射出来,是普通方法 #普通方法需要传参
# res = getattr(Children,"abc","对不起,没有该成员")# 可以为getattr设置默认值,
    如果找不到该成员,在第三个参数上可以设置相应的返回值
class Test1():
    bbb=111
    def myfunc(self):
        print("类中的方法")

obj=Test1()
getattr(Test1,"myfunc")(obj)
print(getattr(Test1,"bbb"))

# setattr() 设置对象/类成员的值
# 设置对象成员属性setattr(obj,"hair","天蓝色的"),设置类的成员方法setattr(Children,"age",func) 其中func自己定义
当然你可以用obj.hair = "天蓝色的"设置对象的属性,但是你知道的是字符串"hair",就需要用setattr了
# delattr() 删除对象/类成员的值 
##### (2)模块的反射#####
    import sys
# sys.modules 返回一个系统字典,字典的键是加载的所有模块 
    print(sys.modules["__main__"])找到此文件的模块(类,方法和属性)

#####异常处理#####
# IndexError 索引超出序列的范围
# KeyError 字典中查找一个不存在的关键字
# NameError 尝试访问一个不存在的变量
# IndentationError  缩进错误
# AttributeError  尝试访问未知的对象属性
# StopIteration 迭代器没有更多的值
# AssertionError  断言语句(assert)失败, assert 5>3  #对,不报错;assert 5<2 #错,报错

try:  #把可能存在问题的代码放到try这个代码块之后,
    code1  #如果没有异常,就不走except
except:
    code2  #如果出现异常直接执行except这个代码块里面内容
# except后可以跟系统错误类型名,若是这种错误类型,则执行这条语句
except IndexError:
    print("我是IndexError错误类")
except KeyError:
    print("我是KeyError错误类")
except:
    print("有异常错误")

# try ... finally 如果有报错,报错让你报,不管有没有错finally中的代码块都要执行
# try ... except ... else  如果不报错就走else分支,报错了就不执行else,不执行except, finally 和 else 不能够同时存在
# for/while ... else ... (了解) 如果循环异常终止(break,或者在函数中通过return终止的),不走else分支

# raise 主动抛出异常,BaseException是所有异常类的父类(基类,超类); Exception是所有普通异常类的父类(基类,超类)
try:
    raise BaseException
except BaseException:
    pass
# raise 后面如果什么也不写 , 默认抛出的是BaseException

try:
    print(a)
except BaseException as b:
    print(666666)
    print(b))

# 拓展
try:
    print("待检测代码")
except:
    print("try代码块出错走这里")
else:
    print("try代码块成功走这里")
finally:
    print("try代码块成功与否都走这里")


"""网络编程"""
    子网掩码和ip地址相与,得到网段,相同网段的两个主机才能够传输数据,子网掩码和ip都可以自己设置
    # 子网掩码:   255.255.255.0  =>  11111111.11111111.11111111.00000000
    # ip1:   192.168.10.12  =>  11000000.10101000.00001010.00001100
    # 子网掩码 & ip1   11000000.10101000.00001010.00000000  得到网段1:192.168.10.0

    # ip2:    192.168.1.16  =>  11000000.10101000.00000001.00010000
    # 子网掩码 & ip2    11000000.10101000.00000001.00000000    得到网段2:192.168.1.0
    # 网段不同,不能互相通信

    # 子网掩码2:    255.255.0.0
    # ip1    192.168.10.12    得到网段1:192.168.0.0
    # ip2    192.168.1.16     得到网段2:192.168.0.0
    # 网段相同,可以互相通信

    # 常用端口
    # IIS(HTTP):80
    # MySQL:3306
    # FTP:21
    # SSH:22

"""socket"""
    一发一收是一对send,recv必须在个数上保持一致,否则收发次数不匹配,会出现异常
# ###tcp基本语法 server 服务端
    import socket
    sk=socket.socket() #1 创建一个socket实例化对象
    sk.bind(("10.0.3.160",8000)) #2 绑定ip和端口(用元组表示)(在网络上注册该主机)
    sk.listen() #3 开启监听
    conn,addr=sk.accept() #4 建立三次握手 其中conn是三次握手成功之后的连接对象,addr是对方ip和端口
    msg=conn.recv(1024) #5 接收数据
    print(msg.decode("utf-8")) #将字节流解码成文字后打印
    conn.send("戏说".encode="utf-8") # 发送数据 (将文字编码成二进制字节流)
    conn.close() #6 四次挥手
    sk.close() #7 退还端口

# ###tcp基本语法 client 客户端
    import socket
    sk=socket.socket() #1 创建一个socket对象
    sk.connect(("10.0.3.160",8000)) #2 连接此ip和端口的服务器
    sk.send("不谓侠".encode("utf-8")) #3 发送数据
    msg=sk.recv(1024) #接收数据
    print(msg.decode("utf-8")) #解码打印
    sk.close() #4 退还端口

########## sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 在测试阶段,可以用这个支持端口复用

# ### tcp 循环发消息 server端
    import socket
    sk = socket.socket()
    sk.bind( ("127.0.0.1",9003) )
    sk.listen()
    while True:
        conn,addr = sk.accept()
        while True:
            res = conn.recv(1024)
            print(res.decode())
            strvar = input("请输入你要给对方的消息:")
            conn.send(strvar.encode())
            if strvar == "q":
                break
        conn.close() #断开一个client端,其他端还连着    
    sk.close()

# ### tcp循环发消息 client端
    import socket
    sk = socket.socket()
    sk.connect( ("127.0.0.1",9003) )
    while True:
        strvar = input("请输入您要发送的消息:")
        sk.send(strvar.encode())
        res = sk.recv(1024)    
        if res == b"q":
            break    
        print(res.decode())
    sk.close()

# ### udp 服务端
    import socket
    sk=socket.socket(type=socket.SOCK_DGRAM) #1.创建一个socket对象,括号里的参数代表使用udp连接
    sk.bind(("127.0.0.1",9000)) # 2.绑定ip,端口号
    # 3.收发数据
    """udp协议,如果作为服务器,第一次需要先接受消息,才能得到对方的ip和端口号"""
    msg,cli_addr = sk.recvfrom(1024)
    print(msg.decode(),cli_addr)
    msg = "iG牛逼"
    sk.sendto(msg.encode("utf-8"),cli_addr)
    sk.close() # 4.关闭连接

# ### 客户端
    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM) # 1.创建socket对象
    msg = "s9总决赛,lpl再造辉煌,凤凰涅槃" # 2.发送消息
    sk.sendto(msg.encode("utf-8"),("127.0.0.1",9000)) # sendto(发送的二进制字节流消息,对方的ip和端口[元组])
    msg,addr = sk.recvfrom(1024)# 接受数据
    print(msg.decode("utf-8"),addr)
    sk.close# 3.关闭udp连接

# udp 默认允许多人同时会话,并且不会黏包
# tcp 默认不允许,只能等当前用户4次挥手之后,才能建立新的链接;可能会黏包

"""struct模块"""    import struct
"""pack和unpack的应用"""
length=len("小祖宗我爱你")
res=struct.pack("i",length) # 把任意长度的整型("i"指代整型)数字转化成具有4个字节固定长度的字节流
tup = struct.unpack("i",res) # 把4个字节值恢复成原本的整型("i"指代整型)数字,返回的是元组
print(tup[0]) #6

"""hashlib 模块 加密算法"""
    import hashlib
# ###基本语法
    hs=hashlib.md5(strvar1.encode("utf-8")) #(1)创建一个md5算法对象,括号里也可不带参数,之后再update补上也行
    hs.update(strvar2.encode()) #(2)把要加密的字符串通过update更新到hs这个对象当中进行运算
    res=hs.hexdigest() #(3)得到加密后的32位字符串
    数据类型需要:二进制字节流
# 常见的加密算法 安全性: hmac > (sha1 sha512) > md5,其中后三个用法相同
# ### hmac
    import hmac
    """可以直接在英文或数字前加b转成字节流"""
    hm=hmac.new(strvar1,strvar2) #参数可以只带一个,就加密一个
    hm.update("777".encode()) #也可以update
    res=hm.hexdigest() #得到加密后的字符串
    """os.urandom(n) 返还长度为 n的随机二进制字节流"""

"""进程"""
    from multiprocessing import Process
    # os.getpid() 获取当前进程号
    # os.getppid() 获取当前父进程号

    def func(n):
        for i in range(1,n+1):
            print("1子进程号>>>%s , 2父进程号>>>%s"%(os.getpid(),os.getppid()))
    if __name__=="__main__":
        n=5
        p=Process(target=func,args=(n,))
        p.start()
        for i in range(1,6):
            print("*"*i)
        print("3子进程号>>>%s , 4父进程号>>>%s"%(os.getpid(),os.getppid()))

# p.join() 等待进程,等待标记的子进程执行完毕后,再执行下方语句,
    主进程(或别的子进程)的任务再继续执行,保证子父进程的同步性
# daemon  守护进程 (陪葬进程)  语法 p.daemon=True
    """
    默认情况下,主进程要等待所有子进程执行完毕之后,才会关闭程序,释放资源
    守护进程进行在主进程代码执行结束之后,就直接关闭;
    守护进程守护的是主进程    必须要写在start()调用之前,进行设置
    """
# lock (互斥锁) 用于多进程中,开进程调用函数时需要传参lock给上锁,
    上锁解锁是一对一对的,进程间谁先抢到资源谁就先上锁,
    from multiprocessing import Process,Lock """with lock: #上锁写法二"""
    # 解锁后下一个进程再继续使用,上锁的时候是同步过程,其他时候是异步
    # lock.acquire()上锁   lock.release()解锁 from multiprocessing import Process,Lock
# Semaphore 信号量,本质上就是锁,同一时间可以上多把锁 sem=Semaphore(3) 同一时
    间可上3把锁,sem.acquire()上锁,sem.release()解锁
    from multiprocessing import Process,Semaphore
# Event 事件 # 阻塞事件:e=Event()生成事件对象e , e.wait()动态给程序加阻塞 ,
    from multiprocessing import Process,Event
    # 程序当中是否加阻塞完全取决于该对象中的 is_set() [默认返回值是False]
    # 如果是True 不加阻塞,如果是False 加阻塞
    # set()方法:将这个属性的值改成True, clear()方法:将这个属性的值改成False
    # is_set()方法  判断当前的属性是否为True  (默认上来是False)
# Queue 进程队列,先进先出 (让进程之间共享队列资源),q=Queue()实例化对象,
    括号里可加参数指定队列长度n,放值q.put("狗子"),取值res=q.get()
    from multiprocessing import Process,Queue
    get_nowait()在没值的时候,直接报错; put_nowait(243) 如果超出了队列长度,直接报错
# JoinableQueue 和普通的Queue队列的不同点是前者可以在队列中元素个数为0时放行,队列中有元素时可以加阻塞
    from multiprocessing import Process,JoinableQueue
    jq=JoinableQueue()实例化,jq.put(xx)存放,jq.get()获取,
    jq.task_done()队列元素计数减一(需要手动减),jq.join() 阻塞
# Manager list dict 能够实现进程之间的数据共享,为了保证数据的准确性,必要时加锁
    from multiprocessing import Process,Manager,Lock #调用函数时需要传参list
# Pool 进程池
    (旧版进程池,没法传参???)
    from multiprocessing import Process,Pool
    ......
    listvar=[]
    p1=Pool(6) #创建进程池对象
    for i in range(10):
        res=p1.apply_async(func) #异步开启进程池,res应该是进程池函数
        listvar.append(res)
    for i in listvar:
        print(i.get()) #获取并打印执行函数的返回值,若只开一个进程池,直接res.get()获取到
    p1.close() #close和join要一起用,让主进程等待进程池执行完再执行
    p1.join()
    res=os.cpu_count() #获取cpu的核心数(逻辑处理器的数量)
    Process : 属于异步并发程序,主进程会默认等待子进程全部执行完毕之后,在终止程序
    Pool    : 属于异步并行程序,在没有任何阻塞的情况下,只要主进程执行完毕,会立刻终止所有子进程;
    p = Pool(6)实例化对进程池对象,代表同一时间最多允许并行6个进程,不写参数就默认开辟逻辑处理器数量个进程
    在进程池中,如果一个进程执行任务的速度太快,会包揽更多的任务执行,就不会创建新的进程;
    res=p1.apply_async(func)异步开启进程池, res=p.apply(func)同步开启进程池,可用res.get()接收到任务的返回值

"""线程""" Thread 线程速度比进程速度快,进程中可以包括多个线程,多线程共享同一份进程资源
    from threading import Thread,currentThread
    t=Thread(target=func)
    t.is_alive()检测线程是否仍然存在,
    t.setName()设置线程名字,t.getName()获取线程名字,currentThread().ident查看线程id号,
    enumerate()返回目前正在运行的线程列表,activeCount()返回目前正在运行的线程数量
# setDaemon 守护线程,等待所有线程执行结束后再终止,守护所有线程,t1.setDaemon(True),
    注意,和Process子进程写法不一样
# Semaphore 信号量,和进程的信号量相同,可以同时上多把锁

"""死锁,递归锁,互斥锁"""
# rlock 递归锁 语法 rlock = RLock(),直接用递归锁代替普通的锁,就可以解决死锁
    from threading import RLock 
    # 死锁: 连续上锁,不解锁,在windows里会发生死锁,阻塞运行
    # 递归锁专门用来解决死锁现象,为了应急,临时解决线上死锁问题,使之正常运行;
# local 线程之间的数据隔离,loc = local()创建对象,loc.val=666,这个数据就是隔离的
    from threading import Thread,local,currentThread
    普通数据在线程里是互通的,引入local, local.变量 就是隔离的
# Event 线程事件,和进程用法一样
    # from threading import Event,Thread
# Queue 线程队列,和进程队列用法相同,队列中一般只能插同一种数据类型,不能混合插入
# LifoQueue 栈队列,后进先出,模拟栈这个数据结构特点,用法同上,只是取得值的顺序不同
# PriorityQueue 排序队列,按照优先级顺序(比如数的大小,字母的大小)进行排序(默认从小到大排序)

"""改良版进程池_线程池"""
    # 新版进程池默认主进程在等待所有子进程执行结束之后,在终止程序,释放资源
    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
# ProcessPoolExecutor 新版进程池
    if __name__ == "__main__":
        (1) 创建进程池对象 ProcessPoolExecutor <==> Pool,括号里面可跟参数开辟多少个进程池
        p = ProcessPoolExecutor()
        (2) 提交异步任务 submit <==> apply_async 还有也不用写 target= 和 args= 了
        res = p.submit(func,66) #res应该是进程池函数,可以传参
        print(res)
        (3) 获取返回值 result <==> get 内部也存在阻塞
        res = res.result()
        print(res)
        (4) shutdown <==> close + join等待进程
        p.shutdown()
        print("主进程执行结束 ... ")
# ThreadPoolExecutor 新版线程池,用法和新版进程池相同
# map 高阶函数,返回迭代器
    tp = ThreadPoolExecutor(5)
    it = tp.map(func,range(20)) #开20个线程池执行函数

"""回调函数"""
    把函数当成参数传递给另外一个函数
    在当前函数执行完毕之后,调用一下传递进来的函数,该函数是回调函数
    (1)add_done_callback 在获取当前线程的返回值的时候,可以异步并发,加快速度
    (2)线程池的回调函数由当前子线程执行,进程池的回调函数由主进程执行
    def func():
        print("===func===")
        return "***"
    def call_back(obj): #obj这个参数必须传,用不用自己看
        print(obj.result(),"===回调函数===")
    tp = ThreadPoolExecutor(5) #开启5个进程池执行一个func任务
    obj = tp.submit(func)
    obj.add_done_callback(call_back) #使用回调函数,异步并发,注意名字固定不可改
    tp.shutdown()
    print("主线程执行完毕"obj.result())
    # 用进程池的写法也是一样

"""协程"""线程是执行任务的主体,协程是给线程分配任务的,可分配多个任务,然后遇到阻塞就跳
# switch 遇到阻塞,可手动调用函数切换任务,缺点是不能自动规避阻塞io
    from greenlet import greenlet   resquests gevent安装一下
  => g1=greenlet(func1) ; g2=greenlet(func2)  创建两个协程对象
    g1.switch() #开启switch协程的方式,跳转(切换)也是用这条语句
    先运行g1,在可能会有阻塞的语句前加一个g2.switch()直接跳到g2执行
    其实是遇到switch就跳,不管后面有没有阻塞,所以要靠人分辨会不会有阻塞,比较傻,看需求使用

# spawn 类似于switch,创建进程并且开始执行,遇到阻塞可以自动切换任务执行,默认在主线程执行结束时
    # 终止一切协程任务(所以一般要加join),缺陷是不能识别部分阻塞,比如time.sleep()
    import gevent
    """将time.sleep()替换成gevent.sleep()就能识别了"""
  => g1=gevent.spawn(func1) ; g2=gevent.spawn(func2) 创建两个协程对象并且开始执行
    注意加 g1.join()和g2.join()
# monkey 可自动切换,并且能够识别各种阻塞
    from gevent import monkey
    monkey.patch_all() #可以把下面引入的所有模块中的阻塞识别出来
    import time
    import gevent
    ...... g1=gevent.spawn(func1) #创建并开始执行任务,不用另外的开启协程语句

    (1)gevent.spawn(函数,参数1,参数2...)启动一个协程任务
    (2)joinall([协程列表]) 等待所有协程任务执行完再往下执行
    (3)value获取协程任务中的返回值g1.value或g2.value

 

面向对象_正则

标签:显示   添加   UNC   length   实例   raise   utf-8   __new__   反向   

原文地址:https://www.cnblogs.com/banbosuiyue/p/13773106.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!