2013-03-04 24 views
1

我有一些远远比实际应该慢的Python代码。使用列表而不是Python中的字典进行优化

#Generate planets 
for t in range(stars*3): #There are 3 planets for every star, but not every star will have 3 planets 
    theplanet=Planet() 

    if random.randint(0,100) <= 25: #25% of planets have life 
     theplanet.tl=random.randint(1,9) #With a random tech level 
    else: 
     theplanet.tl=0 #The rest don't 

    theplanet.star=stardict[random.choice(list(stardict.keys()))]  #Choose a random star 
    theplanet.star.planets+=(theplanet,) #Append the new planet to the star's list of planets 
    theplanet.name=theplanet.star.name+"-"+str(len(theplanet.star.planets)) #Name the planet Starname-X, where X is the length of the star's planets tuple. Since this increases every time a planet is added, it will be 1 for the first planet, 2 for the next, etc... 

    if math.floor((t/(stars*3))*100)==(t/(stars*3))*100: print("Generating planets: "+str((t/(stars*3))*100)+"% done.") 

我很确定这个瓶颈在star=stardict[random.choice(list( etc ...行中。我在这里猜测,但我认为字典是通过搜索字典中的每个条目并查看哪一个条目具有正确的关键字来工作的。我再次假设,列表只读取源自条目号的内存位置的信息,而对于非常大的(准确地说200,000条)列表/字典要快得多。

将dict的条目转换为列表会使此代码更快吗?我将如何做到这一点(我认为我看到了它的功能,现在审查文档...)?有没有其他方法可以让人更快地做到这一点?

+2

您对字典查找的理解似乎不正确。字典是散列表 - 所以查找需要(平均)O(1)操作 - 不需要搜索。 – mgilson 2013-03-04 17:31:55

+0

你认为是错的。字典是基于哈希表的,这些哈希表就是查找事物的最有效方式。 – 2013-03-04 17:32:04

+0

@MarkRansom:虽然OP对字典查找有误解,但将其放在列表中会在技术上将其增加得更多。 (它将摆脱散列步骤和任何碰撞的可能性)。不过,这种改善可能会很微弱。 – 2013-03-04 17:49:05

回答

4

您每次通过循环创建一个列表,但该列表不变。将它移到循环之外。

starlist=list(stardict.keys()) 
... 
    theplanet.star=stardict[random.choice(starlist)]  #Choose a random star 

这个问题几乎可以肯定是不是在字典查找。它们基于散列表,速度非常快。

+0

...和stardict.keys()已经是一个列表,所以你不要't需要外部列表() – tdelaney 2013-03-04 17:48:13

+0

@tdelaney不,它不是(OP使用Python 3,它是一个[view](http://docs.python.org/3/library/stdtypes.html #字典视角))。 – katrielalex 2013-03-04 17:53:29

+0

@tdelaney,即使它不会强迫它,而我只是在复制原始代码。 – 2013-03-04 17:56:54

2
  1. 移动列表生成list(stardict.keys())

  2. 尝试之外分析代码(documentation

  3. 假设你正在运行的CPython,检查你的代码可以与Pypy运行。这可能导致更好的表现,因为它的优化JIT

0

您只使用键作为中间值在stardict中选择一个随机项。您可以直接使用字典的值列表来代替:

#Generate planets 
starlist = stardict.values() 
for t in range(stars*3): #There are 3 planets for every star, but not every star will have 3 planets 
    theplanet=Planet() 

    if random.randint(0,100) <= 25: #25% of planets have life 
     theplanet.tl=random.randint(1,9) #With a random tech level 
    else: 
     theplanet.tl=0 #The rest don't 

    theplanet.star=random.choice(starlist)  #Choose a random star 
    theplanet.star.planets+=(theplanet,) #Append the new planet to the star's list of planets 
    theplanet.name=theplanet.star.name+"-"+str(len(theplanet.star.planets)) #Name the planet Starname-X, where X is the length of the star's planets tuple. Since this increases every time a planet is added, it will be 1 for the first planet, 2 for the next, etc... 

    if math.floor((t/(stars*3))*100)==(t/(stars*3))*100: print("Generating planets: "+str((t/(stars*3))*100)+"% done.") 
相关问题