我发现如果我在开头初始化一个空字典,然后在for循环中添加元素到字典中(大约110,000个键,每个键的值是一个列表,也在循环中增加),速度下降为for循环去.
我怀疑问题是,字典在初始化时并不知道密钥的数量而且它没有做一些非常聪明的事情,所以也许存储冲突变得非常频繁而且速度变慢.
如果我知道密钥的数量以及这些密钥究竟是什么,那么在python中是否有任何方法可以使dict(或哈希表)更有效地工作?我依稀记得,如果你知道密钥,你可以巧妙地设计哈希函数(完美哈希?)并预先分配空间.
我继承了一些Python代码,用于创建巨大的表(最多19列宽5000行).在屏幕上绘制表格需要9秒钟.我注意到使用以下代码添加了每一行:
sTable = sTable + '\n' + GetRow()
Run Code Online (Sandbox Code Playgroud)
哪里sTable是一个字符串.
我把它改为:
sTable += '\n' + GetRow()
Run Code Online (Sandbox Code Playgroud)
我注意到桌子现在出现了六秒钟.
然后我改为:
sTable += '\n%s' % GetRow()
Run Code Online (Sandbox Code Playgroud)
基于这些Python性能提示(仍然是六秒).
由于这被称为大约5000次,它突出了性能问题.但为什么会有这么大的差异呢?为什么编译器没有在第一个版本中发现问题并对其进行优化?
len()关于集合和列表的复杂性同样是O(1).为什么需要更多时间来处理集合?
~$ python -m timeit "a=[1,2,3,4,5,6,7,8,9,10];len(a)"
10000000 loops, best of 3: 0.168 usec per loop
~$ python -m timeit "a={1,2,3,4,5,6,7,8,9,10};len(a)"
1000000 loops, best of 3: 0.375 usec per loop
Run Code Online (Sandbox Code Playgroud)
它是否与特定基准相关,因为它需要更多时间来构建集而不是列表,基准也考虑到了这一点?
如果创建set对象比创建列表需要更多时间,那么潜在的原因是什么?
Python中的所有东西都是一个对象.因此Python中int的大小将比平常大.
>>> sys.getsizeof(int())
24
Run Code Online (Sandbox Code Playgroud)
好的,但为什么还需要12个字节才能进行2?³比较2?³ - 1,而不仅仅是一个?
>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24
Run Code Online (Sandbox Code Playgroud)
我得到的2?³是一个long和2?³-1一个int,但为什么12个字节的区别?
不再直观,我尝试了一些其他的东西:
>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36
Run Code Online (Sandbox Code Playgroud)
a即使它现在可以在int中,仍然存储为long.所以这并不奇怪.但:
>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28
Run Code Online (Sandbox Code Playgroud)
一个新的尺寸.
>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24
Run Code Online (Sandbox Code Playgroud)
回到24个字节,但仍然很长.
我得到的最后一件事:
>>> sys.getsizeof(long())
24
Run Code Online (Sandbox Code Playgroud)
题:
内存存储在这些场景中如何工作? …
我试图了解Python的工作原理(因为我一直都在使用它!).根据我的理解,当你运行python script.py之类的东西时,脚本转换为字节码,然后解释器/ VM/CPython - 实际上只是一个C程序 - 读取python字节码并相应地执行程序.
这个字节码是如何读入的?它是否类似于在C中读取文本文件的方式?我不确定Python代码是如何转换为机器代码的.是这样的情况,Python解释器(CLI中的python命令)实际上只是一个已经转换为机器代码的预编译C程序,然后python字节码文件只是通过该程序?换句话说,我的Python程序是否从未实际转换为机器代码?python解释器是否已经在机器代码中,所以我的脚本永远不必是?
我在使用sys.getsizeof相同的列表时看到了一些不一致的地方.(Python 2.7.5)
>>> lst = [0,1,2,3,4,5,6,7,8,9]
>>> sys.getsizeof(lst)
76
>>> lst2 = list(lst)
>>> sys.getsizeof(lst2)
104
>>> lst3 = list(lst2)
>>> sys.getsizeof(lst3)
104
>>> sys.getsizeof(lst[:])
76
>>> sys.getsizeof(lst2[:])
76
Run Code Online (Sandbox Code Playgroud)
有人有简单的解释吗?
这个消息有点长,有很多例子,但我希望它能帮助我和其他人更好地掌握Python 2.7中变量和属性查找的全部故事.
我正在使用PEP 227(http://www.python.org/dev/peps/pep-0227/)的条款来代码块(例如模块,类定义,函数定义等)和变量绑定(例如作为赋值,参数声明,类和函数声明,for循环等)
我使用的术语变量,可以在不点叫名字,并需要与对象名称限定(如obj.x的属性x对象obj的)名称属性.
Python中有三个范围用于所有代码块,但功能如下:
Python中只有四个块用于函数(根据PEP 227):
变量绑定到块并在块中找到它的规则非常简单:
让我知道验证这条规则的例子,并展示许多特殊情况.对于每个例子,我都会给出我的理解.如果我错了,请纠正我.对于最后一个例子,我不明白结果.
例1:
x = "x in module"
class A():
print "A: " + x #x in module
x = "x in class A"
print locals()
class B():
print "B: " + x #x in module
x = "x in class B"
print locals()
def f(self):
print "f: " + x #x in module
self.x = "self.x in f"
print …Run Code Online (Sandbox Code Playgroud) 我想将此序列的前1024个术语分配给列表.我最初猜测硬编码这个列表将是最快的方法.我还尝试在算法上生成列表,发现这比硬编码更快.因此,我测试了各种折衷方法,使用越来越长的硬编码列表,并在算法上扩展到1024项.我找到的最快的方法是对前128个项目进行硬编码并生成其余的项目.
我想了解为什么对序列中的前128项进行硬编码并计算剩余部分比对所有1024项进行硬编码要快.代码和配置文件结果如下所示,使用Python 3.4.2 Shell(IDLE)和cProfile timeit(
感谢Veedrac对改进的性能分析代码的回答).我已将硬编码列表留在一条非常长的行上,以避免使用数字行混乱问题,但除此之外,代码不需要水平滚动.
def hardcoded():
m = [0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,9,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,10]
def softcoded():
m = [0]
for k in range(10):
m += m
m[-1] += 1
def hybrid():
m = [0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7]
for k in range(3):
m += m
m[-1] += 1
from timeit import Timer
def p_time(func, n=10000):
print(func.__name__)
print(min(Timer(func).repeat(10, n)) / n)
p_time(hardcoded)
p_time(softcoded)
p_time(hybrid)
Run Code Online (Sandbox Code Playgroud)
hardcoded
1.593102711162828e-05
softcoded
1.1183638458442147e-05
hybrid
9.69246251002005e-06
Run Code Online (Sandbox Code Playgroud)
我跑了几次所有的时间并粘贴在最低点.
我知道Python中的集合是无序的,但我对它们显示的"顺序"感到好奇,因为它似乎是一致的.它们似乎每次都以相同的方式乱序:
>>> set_1 = set([5, 2, 7, 2, 1, 88])
>>> set_2 = set([5, 2, 7, 2, 1, 88])
>>> set_1
set([88, 1, 2, 5, 7])
>>> set_2
set([88, 1, 2, 5, 7])
Run Code Online (Sandbox Code Playgroud)
......和另一个例子:
>>> set_3 = set('abracadabra')
>>> set_4 = set('abracadabra')
>>> set_3
set(['a', 'r', 'b', 'c', 'd'])
>>>> set_4
set(['a', 'r', 'b', 'c', 'd'])
Run Code Online (Sandbox Code Playgroud)
我只是好奇为什么会这样.有帮助吗?
为什么是第一个结果False,如果不是True?
>>> from collections import OrderedDict
>>> OrderedDict.__repr__ is OrderedDict.__repr__
False
>>> dict.__repr__ is dict.__repr__
True
Run Code Online (Sandbox Code Playgroud) python ×10
python-internals ×10
performance ×3
python-2.7 ×3
cpython ×2
python-3.x ×2
dictionary ×1
hashtable ×1
html ×1
list ×1
methods ×1
scope ×1
string ×1
variables ×1