2013-03-04 91 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.") 
相關問題