zoukankan      html  css  js  c++  java
  • 面向对象_正则

    # ###

    """面向对象"""
    # ### 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 匹配任意的空白符 
     	 
     " "
    # S 匹配任意非空白符
    # 
     匹配一个换行符 [最好在正则表达式的前面加上r,让转义字符失效,原型化匹配]
    # 	 匹配一个制表符
    
    # ### (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) 边界符 
    # w 卡住左边界(就是匹配以w右边字符为开头的字符)
    # d 卡住右边界(就是匹配以d左边字符为结尾的字符)
    # ^ 整个字符串必须以...开头
    # $ 整个字符串必须以...结尾
        如果正则表达式里面出现了^ $ ,代表把这个字符串看成一个整体,再去匹配
    
    # ###匹配分组
    # (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 使 . 匹配包括换行在内的所有字符(有换行的话匹配出来还有
    )
    # 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
  • 相关阅读:
    java-判断某一年是否是闰年
    java-不用其他变量实现两变量互换
    java基础一标识符,运算符
    robotium学习(三)
    robotium学习(二)
    robotium学习(一)
    AX2012 订单折扣的应用
    AX2012 用户收藏夹复制
    ueditor 改变图片上传路径
    if else 多路分支,多条件运算
  • 原文地址:https://www.cnblogs.com/banbosuiyue/p/13773106.html
Copyright © 2011-2022 走看看