Python学习笔记(八)

类的一些方法

实例方法
(self)的方法是实例方法,实例化之后才能调用

class My:
    def say(self): 
      print('hhh')

静态方法
就是一个普通的函数,只是定义在类里面
用不了实例方法,实例变量,类方法,类变量

class My:
    @staticmethod
    def run():
        print('run')

类方法
(cls)的方法是类方法
不用实例化,直接用类名调用
可以使用类变量,cls.xxx
实例也可以用self.xxx来使用类方法
类方法里面不能用实例方法和实例变量的

class My:
    @classmethod # 装饰器,不改变原来的函数,给函数添加新功能
    def eat(cls): # class
        cls.count
        print('eat')

属性方法
看起来像变量的一个函数
它属于实例方法
不能有入参
调用的时候直接m.func,直接当做变量用,不用加()
它是获取到函数的返回值

class My:
    @property
        def red_pag(self): # 属性方法,没有入参
            return 100

析构函数
__del__,释放内存的时候,销毁的时候自动执行

class My:
    def __del__(self): # 析构函数,实例被销毁的时候自动执行
        print('实例被销毁的时候自动执行')

私有
函数名或者变量名前面加__,这个函数或者变量就是私有的,只能在类里面调用

class My:
    def __cry(self):
        print('wwww')

类的继承:简化代码

子类继承父类,可以使用父类的方法

如果定义和父类一样的方法,会覆盖父类的方法,先查本类有没有该方法,没有的话去父类找

如果想在父类方法的基础上修改,可以使用在父类方法的基础上,调用一下父类的方法

Base.__init__(self,ip,port)
super().__init__(ip,port) 作用相同,父类名修改也不用变

class Base(object): #父类
    def __init__(self,ip,port):
        self.ip = ip
        self.port = port

class MongoDb(Base): #子类
    def __init__(self,ip,port):
        # Base.__init__(self,ip,port)
        super().__init__(ip,port)
        self.client = pymongo.MongoClient(host=self.ip, port=self.port)
    def save(self,data):
        self.client['db']['table'].insert(data)

多进程与多线程

进程:一个进程就是一个程序
线程:线程就是进程里面最小的执行单元,线程在进程里面,干活的还是线程
     一个进程里面可以有多个线程
     一个进程里面最少有1个线程
     每个线程之间都是互相独立的

python里面的多线程,是利用不了多核cpu的,只能利用一个核心的cpu,因为为了保证数据安全有GIL 全局解释器锁,即global interpreter lock

就是python在运行的时候会锁定解释器,就是说在运行的时候只能是一个线程,锁死了,切换不了;每个线程在运行之前都要申请GIL,那么就必须要等上一个线程释放这把锁你才可以申请到,然后执行代码,执行完后,你再交给下一个线程,让它去执行代码,过程如下:

  设置GIL -> 切换到一个线程去执行 -> 运行 -> 把线程设置为睡眠状态 -> 解锁GIL

然后再次重复以上步骤。

单线程下有 IO操作会进行 IO等待,造成不必要的时间浪费,而开启多线程能在
线程 A等待时,自动切换到线程 B,可以不浪费 CPU的资源,从而能提升程序执行效率

多线程任务适用于io密集型任务
磁盘io input,output
网络io
多进程适用于cpu密集型任务
使用cpu多的各种循环处理、计数、排序等等

import threading,time
all_res = [] # 存储返回结果,直接获取不到
def run(name):
    print('子线程:',threading.current_thread())
    time.sleep(5) 
    print(name,'hhh')
    all_res.append(name)

# for i in range(5): # 串行
#     run()
threads = [] # 存放所有的子线程
for i in range(5): # 先统一启动子线程
    t = threading.Thread(target=run,args=(i,)) # 每个线程运行函数
    threads.append(t)
    t.start()

for t in threads: # 统一的去等待子线程执行结束
    t.join()

print('主线程',threading.current_thread())
# t.join()
# while threading.active_count() !=1: # 判断当前活动的线程数不等于1,如果是1个的话说明只有主线程了
#     pass

print(all_res)

加锁

#
from threading import Lock
lock = Lock() # 实例化一把锁
num = 0
def run1():
    global num
    lock.acquire() # 加锁
    num += 1
    lock.release() # 解锁

    with lock: # 自动加锁,解锁
        num += 1

守护线程

守护线程就是守护主线程,主线程死亡,守护线程跟着死,好比关闭QQ,已经开着的聊天窗口跟着关闭

import threading
import time
def run():
    time.sleep(5)
    print('run...')
for i in range(5):
    t = threading.Thread(target=run)
    t.setDaemon(True) # 设为守护线程
    t.start()

print('over')

线程池

import threadpool,requests
url = 'http://q4.qlogo.cn/g?b=qq&nk=%s&s=140' def down_img(qq_num): res = requests.get(url%qq_num).content with open('%s.jpg'%qq_num,'wb') as fw: fw.write(res) pool = threadpool.ThreadPool(200) #线程池的大小 all_requests = threadpool.makeRequests(down_img,all_qq)#分配数据 for r in all_requests: pool.putRequest(r) #发请求 #[pool.putRequest(r) for r in all_requests] # pool.wait()#等待所有线程运行完 print('done!下载完成。')

多进程、进程池

from multiprocessing import Process,Pool,active_children
url = 'http://q4.qlogo.cn/g?b=qq&nk=%s&s=140'
def down_img(qq_num):
    res = requests.get(url%qq_num).content
    with open('%s.jpg'%qq_num,'wb') as fw:
        fw.write(res)

if __name__ == '__main__':
    for qq in all_qq:
        p = Process(target=down_img,args=(qq,)) #启动多进程
        p.start()
    
    pool = Pool(5)#指定进程池的大小
    list(pool.map(down_img,all_qq)) #运行 使用进程池
原文地址:https://www.cnblogs.com/qingmingzy/p/9403602.html