Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python dict:在Python中,匹配一个数字键和一个单词之间有速度上的差异吗?_Python_Mysql - Fatal编程技术网

Python dict:在Python中,匹配一个数字键和一个单词之间有速度上的差异吗?

Python dict:在Python中,匹配一个数字键和一个单词之间有速度上的差异吗?,python,mysql,Python,Mysql,在一个包含50个项目的Python dict中,匹配一个整数键(2个数字)来查找字符串值与匹配一个字符串键(5-10个以上字母)来查找大量循环(100000个以上)上的整数值相比,会有任何已知的明显速度差异吗 作为小额奖金;在MYSQL和Python中执行这样的活动有什么好处吗 功能是一个有用的练习,但你必须带着它 一粒盐。这很难做到 以准确和有意义的方式进行基准测试 人们关心的是整体性能,而不是个人特征 表演 我发现使用“测试线束”更容易运行 以可比的方式提供不同的备选方案 对于字典查找,下面

在一个包含50个项目的Python dict中,匹配一个整数键(2个数字)来查找字符串值与匹配一个字符串键(5-10个以上字母)来查找大量循环(100000个以上)上的整数值相比,会有任何已知的明显速度差异吗


作为小额奖金;在MYSQL和Python中执行这样的活动有什么好处吗 功能是一个有用的练习,但你必须带着它 一粒盐。这很难做到 以准确和有意义的方式进行基准测试 人们关心的是整体性能,而不是个人特征 表演

我发现使用“测试线束”更容易运行 以可比的方式提供不同的备选方案

对于字典查找,下面是一个使用PyPI模块的示例。 100 随机运行,设置N=50项的
dict
s 每个--
int
键和
str
值或 反向,然后尝试两种
尝试
/
除外
s 和
get
访问范例。代码如下:

import benchmark
from random import choice, randint
import string

def str_key(length=8, alphabet=string.ascii_letters):
    return ''.join(choice(alphabet) for _ in xrange(length))

def int_key(min=10, max=99):
    return randint(min, max)

class Benchmark_DictLookup(benchmark.Benchmark):

    each = 100 # allows for differing number of runs

    def setUp(self):
        # Only using setUp in order to subclass later
        # Can also specify tearDown, eachSetUp, and eachTearDown
        self.size = 1000000
        self.n = 50
        self.intdict = { int_key():str_key() for _ in xrange(self.n) }
        self.strdict = { str_key():int_key() for _ in xrange(self.n) }
        self.intkeys = [ int_key() for _ in xrange(self.size) ]
        self.strkeys = [ str_key() for _ in xrange(self.size) ]

    def test_int_lookup(self):
        d = self.intdict
        for key in self.intkeys:
            try:
                d[key]
            except KeyError:
                pass

    def test_int_lookup_get(self):
        d = self.intdict
        for key in self.intkeys:
            d.get(key, None)

    def test_str_lookup(self):
        d = self.strdict
        for key in self.strkeys:
            try:
                d[key]
            except KeyError:
                pass

    def test_str_lookup_get(self):
        d = self.strdict
        for key in self.strkeys:
            d.get(key, None)


class Benchmark_Hashing(benchmark.Benchmark):

    each = 100 # allows for differing number of runs

    def setUp(self):
        # Only using setUp in order to subclass later
        # Can also specify tearDown, eachSetUp, and eachTearDown
        self.size = 100000
        self.intkeys = [ int_key() for _ in xrange(self.size) ]
        self.strkeys = [ str_key() for _ in xrange(self.size) ]


    def test_int_hash(self):
        for key in self.intkeys:
            id(key)

    def test_str_hash(self):
        for key in self.strkeys:
            id(key)


if __name__ == '__main__':
    benchmark.main(format="markdown", numberFormat="%.4g")
结果是:

$ python dictspeed.py

Benchmark Report
================

Benchmark DictLookup
--------------------

          name | rank | runs |   mean |      sd | timesBaseline
---------------|------|------|--------|---------|--------------
int lookup get |    1 |  100 | 0.1756 | 0.01619 |           1.0
str lookup get |    2 |  100 | 0.1859 | 0.01477 | 1.05832996073
    int lookup |    3 |  100 | 0.5236 | 0.03935 | 2.98143047487
    str lookup |    4 |  100 | 0.8168 | 0.04961 | 4.65108861267

Benchmark Hashing
-----------------

    name | rank | runs |     mean |        sd | timesBaseline
---------|------|------|----------|-----------|--------------
int hash |    1 |  100 | 0.008738 |  0.000489 |           1.0
str hash |    2 |  100 | 0.008925 | 0.0002952 | 1.02137781609

Each of the above 600 runs were run in random, non-consecutive order by
`benchmark` v0.1.5 (http://jspi.es/benchmark) with Python 2.7.5
Darwin-13.4.0-x86_64 on 2014-10-28 19:23:01.
结论:字典中的字符串查找并不比整数查找贵多少但是被认为是python式的“请求原谅而不是许可”范式比简单地使用
get
方法调用花费的时间要长得多。此外,散列字符串(至少大小为8)并不比散列整数昂贵多少

但是,如果在不同的实现上运行,事情会变得更加有趣,比如PyPy:

$ pypy dictspeed.py

Benchmark Report
================

Benchmark DictLookup
--------------------

          name | rank | runs |    mean |        sd | timesBaseline
---------------|------|------|---------|-----------|--------------
int lookup get |    1 |  100 | 0.01538 | 0.0004682 |           1.0
str lookup get |    2 |  100 | 0.01993 |  0.001117 |   1.295460397
    str lookup |    3 |  100 |  0.0203 |  0.001566 | 1.31997704025
    int lookup |    4 |  100 | 0.02316 |  0.001056 | 1.50543635375

Benchmark Hashing
-----------------

    name | rank | runs |      mean |        sd | timesBaseline
---------|------|------|-----------|-----------|--------------
str hash |    1 |  100 | 0.0005657 | 0.0001609 |           1.0
int hash |    2 |  100 |  0.006066 | 0.0005283 |  10.724346492

Each of the above 600 runs were run in random, non-consecutive order by
`benchmark` v0.1.5 (http://jspi.es/benchmark) with Python 2.7.8
Darwin-13.4.0-x86_64 on 2014-10-28 19:23:57.
PyPy的速度大约是最佳情况下的11倍,但比率相差很大。PyPy不会像CPython那样承受巨大的异常处理成本。而且,对整数进行哈希运算比对字符串进行哈希运算慢10倍。如果有意外的结果呢

我本想尝试Python3,但
基准测试
在那里安装得不好。我还尝试将字符串长度增加到50。这并没有显著改变结果、比率或结论


总的来说,散列和查找速度非常快,除非你必须以数百万或数十亿的速度进行,或者有非常长的键,或者其他一些不寻常的情况,否则开发人员通常不必担心他们的微性能。

为什么不自己测量一下呢
timeit
是您的朋友。字典查找是键->值的哈希映射。检索时间应该是
O(1)
@g.d.d.c-你能稍微解释一下最后一部分吗?@MihaiMaruseac Cool beans!我不知道它的存在。我想我最终可能会测试它,但我不确定这其中的任何部分是否是常识。例如,“当然,数字更快,数字/字节更少”或类似性质的任何东西。
O(1)
意味着从字典中检索单个键不应随字典的大小而变化。检索任何特定值所做的工作都是常量-散列键、检查存储桶、识别冲突、返回。如果您认为有人会建议使用
try更像Pythonic。除了
而不是
get()
,您要么误解了人,要么听错了人的话。是的,EAFP比LBYL更受鼓励,但是
get()
不是LBYL的一个例子。因此,如果我读对了,如果我要进行160k次值查找(通过str键),查找本身总共需要大约4.6分钟(而不是4.95分钟),在PyPy中只需要24秒。我从来没有真正看过皮比——天哪,牛跑得真快。尽管如此,数字仍然很低。感谢您运行测试并包含代码-现在我一定会在将来运行我自己的测试。干得好@JonathanEunice@JohnY我同意这是一个坏主意,但多年来我看到了多个教程和讨论()建议对
key in d
d.get(key,None)
方法进行异常处理。几年来,这似乎是一个相当有宗教/争议的问题
get
是一个很好的例子,因为它可以防止不愉快的异常结果。如果您喜欢只调用d中的
条件LBYL,那么
get
是一个更大的飞跃,但不要失败。@JonathanEunice:如果有“飞跃但不要失败”这样的事情,那么
试试..除此之外
也符合该定义!我想说,把
get()
看作是一种有效的
try。但是我可以把
get()
放在一个与
try
中的
完全不同的类别中。关键是Python不是一次只选择一个二分法,总是选择二分法的一端而不是另一端。它是关于同时平衡许多相互竞争的关注点并灵活地导航它们(参见禅宗)。@JonathanEunice:
get()
是Pythonic,因为如果您的用例确实符合
get()
提供的内容,那么它比其他任何一种方法都具有更好的可读性和实用性。