在Python函数中使用大数据结构时的效率

在Python函数中使用大数据结构时的效率,python,pass-by-reference,function-call,Python,Pass By Reference,Function Call,我需要使用一个大数据结构,更具体地说,一个大字典来完成查找工作 首先,我的代码是这样的: #build the dictionary blablabla #look up some information in the ditionary blablabla 由于我需要多次查找,我开始意识到将其作为一个函数实现是一个好主意,比如lookup(info) 然后问题来了,我该如何处理这本大字典 我应该使用lookup(info,dictionary)将其作为参数传递,还是应该在main()中初始化

我需要使用一个大数据结构,更具体地说,一个大字典来完成查找工作

首先,我的代码是这样的:

#build the dictionary
blablabla
#look up some information in the ditionary
blablabla
由于我需要多次查找,我开始意识到将其作为一个函数实现是一个好主意,比如lookup(info)

然后问题来了,我该如何处理这本大字典

我应该使用lookup(info,dictionary)将其作为参数传递,还是应该在main()中初始化dictionary并将其用作全局变量

第一个看起来更优雅,因为我认为维护全局变量很麻烦。 但另一方面,我不确定将大字典传递给函数的效率。它将被多次调用,如果参数传递效率低下,那么它肯定会成为一场噩梦

谢谢

编辑1:

我刚刚做了一个以上两种方式的实验:

下面是代码片段。lookup1实现传递查找的参数,而lookup2使用全局数据结构“big_dict”

这是输出:

查找1为8.410885
lookup2是8.157661
班级为4.525721

看来这两种方法几乎是一样的,是的,全局变量方法更有效一点

编辑2:


添加了Amber建议的类版本,然后再次测试效率。然后我们可以从结果中看出Amber是正确的,我们应该使用类版本。

两者都不是。使用一个类,该类专门用于将函数(方法)与数据(成员)分组:


回答核心问题,参数传递不是低效的,你的值不会被复制。Python到处传递引用,这并不是说参数的传递方式符合众所周知的“按值传递”或“按引用传递”方案

最好将其想象为使用调用者提供的引用值初始化被调用函数的局部变量值,引用值通过值传递


不过,使用类的建议可能是个好主意。

是的,在python中,所有内容都是通过引用传递的,结构在传递给函数时不会被复制。你可以把字典做成你喜欢的大小,除非你明确地这样做,否则它不会复制它。我猜OP是从C背景迁移而来的。@MarkR:不,在Python中所有东西都是按值传递的。对象根本不是值。所有的值都是引用。Python中的字典相当有效,大约有20亿个条目(假设您有这方面的理论)。这个限制是由于它内部使用的哈希值仅为32位,在这一点上,一个人开始得到太多的哈希冲突。但是,在Python3.3中,64位体系结构可能会改变这个限制,这样就不会再有这个限制了。谢谢!经过验证,结果表明类是一个更好的选择
class CityDict():
    def __init__():
        self.code_dict = get_code_dict()
    def get_city(city):
        try:
            return self.code_dict[city]
        except Exception:
            return None         

def get_code_dict():
    # initiate code dictionary from file
    return code_dict

def lookup1(city, city_code_dict):
    try:
        return city_code_dict[city]
    except Exception:
        return None

def lookup2(city):
    try:
        return big_dict[city]
    except Exception:
        return None


t = time.time()
d = get_code_dict()
for i in range(0, 1000000):
    lookup1(random.randint(0, 10000), d)

print "lookup1 is %f" % (time.time() - t)


t = time.time()
big_dict = get_code_dict()
for i in range(0, 1000000):
    lookup2(random.randint(0, 1000))
print "lookup2 is %f" % (time.time() - t)


t = time.time()
cd = CityDict() 
for i in range(0, 1000000):
    cd.get_city(str(i))
print "class is %f" % (time.time() - t)
class BigDictLookup(object):
    def __init__(self):
        self.bigdict = build_big_dict() # or some other means of generating it
    def lookup(self):
        # do something with self.bigdict

def main():
    my_bigdict = BigDictLookup()
    # ...
    my_bigdict.lookup()
    # ...
    my_bigdict.lookup()