类的一些方法
实例方法
(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)) #运行 使用进程池
来源: http://www.bubuko.com/infodetail-2709970.html