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)) #运行 使用进程池