纯粹的python优化(数据结构、cache、推导、生成器)

learn from 《Python高性能(第2版)》

1. 数据结构与算法

列表、双端队列

  • list 底层是数组,在 开头 插入和删除的时间复杂度 O(n), 在结尾插入和删除是 O(1),访问任意元素是 O(1)
  • deque 底层是 双向链表实现,开头结尾操作时间复杂度均为 O(1),代价是访问中间元素是 O(n)
  • 在有序列表里查找元素,可以使用二分查找,bisect 模块,时间O(log n)

字典、反向索引

在N篇文档中查找包含 X 单词的所有文档 [doc for doc in docs if 'X' in doc]
当N非常大的时候这样的效率是很低的

首次可以生成 单词 : [包含该单词的 doc 的 id],以后每次查询的时间复杂度是 O(1)

集合

底层也是哈希

插入和删除元素的时间复杂度都是 O(log n)

heapq

>>> import heapq
>>> c = [10,1,3,2,5]
>>> heapq.heapify(c)
>>> c
[1, 2, 3, 10, 5]
>>> heapq.heappop(c)  # 弹出最小的值 时间复杂度O(1)
1
>>> heapq.heappush(c, 9)
>>> c
[2, 5, 3, 10, 9]

PriorityQueue 优先队列,它是线程、进程安全的

>>> from queue import PriorityQueue
>>> q = PriorityQueue()
>>> for x in [2, 5, 10, 9, 1]:
...     q.put(x)
>>> q
<queue.PriorityQueue object at 0x0000017DD91EED08>
>>> while not q.empty():
...     q.get()  # 取出最小值
...
1
2
5
9
10

如果是元组等,将按第一个元素排序,一样的话,按第二个,以此类推

>>> q.put([1,2])
>>> q.put([1,3])
>>> q.put([1,-1])
>>> q.get()
[1, -1]
>>> q.get()
[1, 2]
>>> q.get()
[1, 3]

字典树

标准库没有实现,有第三方包实现
字典树可以快速查找前缀字符串,课用于文字补全

pip install patricia-trie

另外还有 C语言编写优化过的字典树库 datriemarisa-trie

https://pypi.org/project/datrie/
https://pypi.org/project/marisa-trie/0.7.1/

from random import choice
from patricia import trie
from string import ascii_lowercase
import cProfiledef random_string(length):return ''.join(choice(ascii_lowercase) for i in range(length))def gen_strings():strings = [random_string(32) for _ in range(100000)]return stringsstrings = gen_strings()
strings_dict = {s: 0 for s in strings}
strings_trie = trie(**strings_dict)def func1():matches = [s for s in strings if s.startswith('abc')]print(matches)def func2():matches = list(strings_trie.iter('abc'))print(matches)if __name__ == "__main__":cProfile.run('func1()', sort='tottime')cProfile.run('func2()', sort='tottime')
D:\ProgramData\Anaconda3\envs\cv\python.exe D:/gitcode/Python_learning/Python-High-Performance-Second-Edition-master/Chapter02/trie.py 
['abcimostjvrhrhuswjhshhsnoyawtuaq', 'abcymrvuyenkyuppjuwnstzpaxarjpjo', 'abcbltxrvuktanyoiezntijmaryojbvg', 'abckxrzwjmdjaekmiqquezgwjabdhohe', 'abcecoluitahquyqxoidjiwaupatgszd', 'abcppzcrqjxgzuoiuskethybnlgbougt', 'abcbaznirxvyhnvabmbhwmsefdtultpj']100006 function calls in 0.036 secondsOrdered by: internal timencalls  tottime  percall  cumtime  percall filename:lineno(function)100000    0.019    0.000    0.019    0.000 {method 'startswith' of 'str' objects}1    0.017    0.017    0.036    0.036 trie.py:18(<listcomp>)1    0.000    0.000    0.036    0.036 {built-in method builtins.exec}1    0.000    0.000    0.000    0.000 {built-in method builtins.print}1    0.000    0.000    0.036    0.036 trie.py:17(func1)1    0.000    0.000    0.036    0.036 <string>:1(<module>)1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}['abcimostjvrhrhuswjhshhsnoyawtuaq', 'abcymrvuyenkyuppjuwnstzpaxarjpjo', 'abcbltxrvuktanyoiezntijmaryojbvg', 'abcbaznirxvyhnvabmbhwmsefdtultpj', 'abckxrzwjmdjaekmiqquezgwjabdhohe', 'abcecoluitahquyqxoidjiwaupatgszd', 'abcppzcrqjxgzuoiuskethybnlgbougt']83 function calls (66 primitive calls) in 0.000 secondsOrdered by: internal timencalls  tottime  percall  cumtime  percall filename:lineno(function)1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}25/8    0.000    0.000    0.000    0.000 patricia.py:57(_items)1    0.000    0.000    0.000    0.000 {built-in method builtins.print}3    0.000    0.000    0.000    0.000 patricia.py:161(_next)1    0.000    0.000    0.000    0.000 trie.py:21(func2)1    0.000    0.000    0.000    0.000 patricia.py:354(iter)8    0.000    0.000    0.000    0.000 patricia.py:51(_keys)7    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}9    0.000    0.000    0.000    0.000 {method 'values' of 'dict' objects}8    0.000    0.000    0.000    0.000 {method 'pop' of 'list' objects}1    0.000    0.000    0.000    0.000 patricia.py:366(_accumulate)8    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}1    0.000    0.000    0.000    0.000 <string>:1(<module>)3    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}5    0.000    0.000    0.000    0.000 {built-in method builtins.len}1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

可以看出 trie 快了至少好几十倍

2. 缓存

lru_cache

例如:计算斐波那契数列,动态规划
python 有 functools.lru_cache装饰器,可指定大小 maxsize

>>> from functools import lru_cache
>>> @lru_cache()
... def sum2(a, b):
...     print('calculate')
...     return a+b
...
>>> sum2(1,2)
calculate
3
>>> sum2(1,2)  # 没有进行计算,直接输出结果了
3
>>> sum2(1,3)
calculate
4

缓存性能查看

>>> sum2.cache_info()
CacheInfo(hits=1, misses=2, maxsize=128, currsize=2)
>>> sum2.cache_clear()
>>> sum2.cache_info()
CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)
from functools import lru_cache
import cProfile
@lru_cache(maxsize=None)
def fibonacci_mem(n):if n < 1:  return 1else:  return fibonacci_mem(n - 1) + fibonacci_mem(n - 2)def fibonacci(n):if n < 1:  return 1else:  return fibonacci(n - 1) + fibonacci(n - 2)if __name__ == '__main__':cProfile.run('fibonacci(30)', sort='tottime')print(fibonacci_mem)cProfile.run('fibonacci_mem(30)', sort='tottime')

输出:

D:\ProgramData\Anaconda3\envs\cv\python.exe D:/gitcode/Python_learning/Python-High-Performance-Second-Edition-master/Chapter02/cache.py 4356620 function calls (4 primitive calls) in 1.695 secondsOrdered by: internal timencalls  tottime  percall  cumtime  percall filename:lineno(function)
4356617/1    1.695    0.000    1.695    1.695 cache.py:8(fibonacci)1    0.000    0.000    1.695    1.695 {built-in method builtins.exec}1    0.000    0.000    1.695    1.695 <string>:1(<module>)1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}<functools._lru_cache_wrapper object at 0x000001882C23E550>35 function calls (4 primitive calls) in 0.000 secondsOrdered by: internal timencalls  tottime  percall  cumtime  percall filename:lineno(function)1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}32/1    0.000    0.000    0.000    0.000 cache.py:3(fibonacci_mem)1    0.000    0.000    0.000    0.000 <string>:1(<module>)1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

joblib

提供了基于磁盘的简单缓存

pip install joblib
import os
from joblib import Memory
mem = Memory(cachedir=os.path.join(os.path.dirname(__file__), 'cache_dir'))@mem.cache
def fibonacci(n):if n < 1:  return 1else:  return fibonacci(n - 1) + fibonacci(n - 2)if __name__ == '__main__':fibonacci(32)

在这里插入图片描述

3. 推导和生成器

两者可以替代显式的 for 循环,效率比 for 循环要高

对生成器对象进行迭代时,每次只返回一个计算结果,可以节省内存使用

jupyter 中

%load_ext memory_profiler
import osnumbers = range(1000000)def map_comprehension(numbers):a = [n * 2 for n in numbers]b = [n ** 2 for n in a]c = [n ** 0.33 for n in b]return max(c)%memit map_comprehension(numbers) 
peak memory: 236.46 MiB, increment: 112.98 MiB
def map_normal(numbers):a = map(lambda n: n * 2, numbers)b = map(lambda n: n ** 2, a)c = map(lambda n: n ** 0.33, b)return max(c)%memit map_normal(numbers)
peak memory: 123.73 MiB, increment: 0.00 MiB

可以看出 生成器版本更节省内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/470849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决在vue init webpack my-project卡住的问题(已解决)

执行vue init webpack test命令&#xff1a; 然后cd test&#xff0c;然后cnpm install 或者 npm install --registryhttps://registry.npm.taobao.org 然后执行 npm run dev命令&#xff1a;

十一、案例:TabBar的封装

0、案例效果演示&#xff1a; 一、TabBar实现思路 如果在下方有一个单独的TabBar组件&#xff0c;你如何封装 自定义TabBar组件&#xff0c;在APP中使用 让TabBar出于底部&#xff0c;并且设置相关的样式 TabBar中显示的内容由外界决定 定义插槽 flex布局平分TabBar 自定义Ta…

POJ 3126 Prime Path

水题&#xff1a;直接判断素数bfs 1 #include <iostream>2 #include <cstdio>3 #include <cstring>4 #include <sstream>5 #include <algorithm>6 #include <list>7 #include <map>8 #include <vector>9 #include <queue&g…

十二、Promise的学习笔记(Promise的基本使用、链式编程、all())

一、认识Promise ES6中一个非常重要和好用的特性就是Promise 但是初次接触Promise会一脸懵逼&#xff0c;这TM是什么东西&#xff1f;看看官方或者一些文章对它的介绍和用法&#xff0c;也是一头雾水。 Promise到底是做什么的呢&#xff1f; Promise是异步编程的一种解决方…

十三、Vuex学习笔记

一、Vuex是做什么的? 官方解释&#xff1a;Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 它采用 集中式存储管理 应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension&#xf…

SQL Server2008附加数据库失败

今天旁晚时分&#xff0c;我准备把老师在上课时候发给我们的一个数据库附加到我的SQL Server2008上面去&#xff0c;本来在学校机房用的SQL Server2000是很顺利地就成功了&#xff0c;但是把*.mdf文件附加到我的08上就不行了&#xff0c;出现了下面的问题&#xff08;图是我 百…

数据解析学习笔记(正则解析、bs4解析、xpath解析)

聚焦爬虫:爬取页面中指定的页面内容。 - 编码流程&#xff1a; - 指定url - 发起请求 - 获取响应数据 - 数据解析 - 持久化存储 数据解析分类&#xff1a; 正则bs4xpath&#xff08;***&#xff09; 数据解析原理概述&#xff1a; - 解析的局部的文本内容都会在标签之间或者标…

Rasa NLU 实践

文章目录1. 目录结构2. nlu.yml3. config.yml4. domain.yml5. 实践learn from https://github.com/Chinese-NLP-book/rasa_chinese_book_code 1. 目录结构 2. nlu.yml version: "3.0" nlu:- intent: greetexamples: |- 你好- hello- hi- 喂- 在么- intent: goodbye…

python3爬虫验证码识别——超级鹰打码平台的使用实战:识别古诗文网登录页面中的验证码

一、验证码和爬虫之间的爱恨情仇&#xff1f; 反爬机制&#xff1a;验证码.识别验证码图片中的数据&#xff0c;用于模拟登陆操作。 二、识别验证码的操作&#xff1a; 人工肉眼识别。&#xff08;不推荐&#xff09;第三方自动识别&#xff08;推荐&#xff09; - 超级鹰打…

python爬虫模拟登录人人网

模拟登录&#xff1a;爬取基于某些用户的用户信息。 需求1&#xff1a;对人人网进行模拟登录。 点击登录按钮之后会发起一个post请求post请求中会携带登录之前录入的相关的登录信息&#xff08;用户名&#xff0c;密码&#xff0c;验证码…&#xff09;验证码&#xff1a;每次…

python爬虫——代理IP

代理&#xff1a;破解封IP这种反爬机制。 什么是代理&#xff1a; 代理服务器。 代理的作用&#xff1a; 突破自身IP访问的限制。隐藏自身真实IP 代理相关的网站&#xff1a; - 快代理 西祠代理www.goubanjia.comhttps://ip.jiangxianli.com/?page1 代理ip的类型&#…

ES 安装、search、index、doc

文章目录1. 安装2. search3. index4. doc CRUDop_type获取 doc 元字段只获取 doc 源数据删除 docupdate doc1. 安装 https://www.elastic.co/cn/ 下载 https://www.elastic.co/cn/downloads/past-releases/elasticsearch-8-5-3 https://www.elastic.co/cn/downloads/past-rele…

UWP开发入门(十一)——Attached Property的简单应用

UWP中的Attached Property即附加属性&#xff0c;在实际开发中是很常见的&#xff0c;比如Grid.Row: <Grid Background"{ThemeResource ApplicationPageBackgroundThemeBrush}"><Grid.RowDefinitions><RowDefinition></RowDefinition><Ro…

一、bootstrap4基础(布局系统、栅格系统、显示与隐藏、对齐与排列、内容排版、代码与图文、表格样式、颜色和边框、工具类)

1.1 Bootstrap简单介绍 1.2 Bootstrap结构 1.3 Bootstrap安装和测试 1.4 布局系统 1.5 栅格系统 4.6 栅格等级 1.7 显示与隐藏 1.7 对齐与排列 1.8 内容排版 1.9 代码与图文 1.9.1 设置图片居中显示 1.9.1 设置图片响应式显示 1.9.2 设置图片缩略图显示&#xff0c;以及显示的位…

二、bootstrap4基础(flex布局)

1.1 Flex弹性布局&#xff08;一&#xff09; <div class"d-flex flex-column border border-danger justify-content-end mb-5" style"height: 200px;"><div class"p-2 border border-success">one</div><div class"…

三、bootstrap4 组件(警告和提示框、徽章和面包屑、按钮按钮组、卡片、列表组、导航和选项卡、分页和进度条、巨幕和旋转图标、轮播图、折叠菜单、下拉菜单、导航条、滚动监听、轻量弹框、模态框、表单)

1.1 警告提示框 1.2 徽章和面包屑 1.3 按钮和按钮组 1.4 卡片 1.5 列表组 1.6 导航和选项卡 1.7 分页和进度条 1.8 巨幕和旋转图标 1.9 轮播图 1.10 折叠菜单 1.11 下拉菜单 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title&…

十三、axios框架学习

一、axios的基本使用 1.1 安装axios 执行命令&#xff1a;npm install axios --save 1.2 发送get请求演示 1.3 发送并发请求 有时候, 我们可能需求同时发送两个请求 使用axios.all, 可以放入多个请求的数组.axios.all([]) 返回的结果是一个数组&#xff0c;使用 axios.sp…

LeetCode解题汇总目录

此篇为学习完《数据结构与算法之美》后&#xff0c;在LeetCode刷题的汇总目录&#xff0c;方便大家查找&#xff08;CtrlFind&#xff09;&#xff0c;一起刷题&#xff0c;一起PK交流&#xff01;如果本文对你有帮助&#xff0c;可以给我点赞加油&#xff01; Updated on 2022…

一、node.js搭建最简单的服务器

node.js搭建最简单的服务器 代码演示&#xff1a; // 1. 加载http核心模块 var http require(http)// 2. 使用http.createServer()方法创建一个Web服务器 // 返回一个Server实例 var server http.createServer()// 3. 服务器干嘛&#xff1f; // 提供服务&#xff1a; 对数…

DDD 领域驱动设计-如何 DDD?

注&#xff1a;科比今天要退役了&#xff0c;我是 60 亿分之一&#xff0c;满腹怀念&#xff5e;??? 前几天看了园友的一篇文章《我眼中的领域驱动设计》&#xff0c;文中有段话直击痛点&#xff1a;有人误认为项目架构中加入 Repository&#xff0c;Domain&#xff0c;Valu…