2011-03-20 17 views
1

我使用字典的get()方法來根據變量鍵值選擇一個案例。問題是,它一直在爲密鑰選擇錯誤的情況。我不確定我是否用正確的詞語來解釋它,但是代碼應該足夠清楚。使用字典的'get'方法來選擇案例。爲什麼選擇錯誤的東西?

di_eqns = {"PSME": Pred_PSME(liLn), "ABAM":Pred_ABAM(liLn), \ 
      "ABCO":Pred_Abies(liLn), "ABGR":Pred_Abies(liLn), \ 
      "ABLA":Pred_Abies(liLn), "ABMA":Pred_Abies(liLn), \ 
      "ABSH":Pred_Abies(liLn), "ABPR":Pred_ABPR(liLn), \ 
      "CADE27":Pred_Cedar(liLn), "CHLA":Pred_Cedar(liLn), \ 
      "CHNO":Pred_Cedar(liLn), "THPL":Pred_Cedar(liLn), \ 
      "LALY":Pred_LALY(liLn), "LAOC":Pred_LAOC(liLn), \ 
      "PIEN":Pred_PIEN(liLn), "PISI":Pred_PISI(liLn), \ 
      "PIAL":Pred_Pinus(liLn), "PIJE":Pred_Pinus(liLn), \ 
      "PIMO3":Pred_Pinus(liLn), "PICO":Pred_PICO(liLn), \ 
      "PILA":Pred_PILA(liLn), "PIPO":Pred_PIPO(liLn), \ 
      "TSHE":Pred_TSHE(liLn), "TSME":Pred_TSME(liLn), \ 
      "JUOC":Pred_JUOC(liLn), "TABR":Pred_TSHE(liLn), \ 
      "ALRU2":Pred_ALRU2(liLn), "ACCI":Pred_SMBGr(liLn), \ 
      "ACGL":Pred_SMBGr(liLn), "ACMA3":Pred_ACMA3(liLn), \ 
      "CONU4":Pred_ACMA3(liLn), "ALRH2":Pred_AACWGr(liLn), \ 
      "SASC":Pred_AACWGr(liLn), "SALIX":Pred_AACWGr(liLn), \ 
      "ARME":Pred_ARME(liLn), "BEPA":Pred_BEPA(liLn), \ 
      "BEPAC":Pred_BEPA(liLn), "CHCH7":Pred_CHCH7(liLn), \ 
      "FRLA":Pred_MHGr(liLn), "PREM":Pred_MHGr(liLn), \ 
      "PRVI":Pred_MHGr(liLn), "PRUNU":Pred_MHGr(liLn), \ 
      "LIDE3":Pred_LIDE3(liLn), "POBAT":Pred_POBAT(liLn), \ 
      "POTR5":Pred_POTR5(liLn), "QUCH2":Pred_QUCH2(liLn), \ 
      "QUGA4":Pred_QUGA4(liLn), "QUKE":Pred_QUKE(liLn), \ 
      "UMCA":Pred_UMCA(liLn)} 
try: li_pred = di_eqns.get(liLn[2]) 

這裏是清單(從一個文本文件中的行),關鍵是從時走錯了功能拍攝(它去Pred_PSME):

['1347189', '20571', 'PIEN', 'Picea engelmannii', 'Y', 'Y', '66.294', 
'0.3452', '35.7418', '', '5.0996', '0', '1', '1.1324', '3.2803', '2.3057', 
'16.7282', '5520.306', '127.30', '70.73', '92.10', '0.00', '5.68', '2.37', 
'7.25', '79.16', '76.79', '290.15', '219.41', '135.37', '0.00', '0.00', 
'951.78', '719.74', '259.68', '251.89', '444.05', '0.00', '0.00', '', 
'12.70', '10.16', '15.24', '0.02', '0.04', '0.19', '0.19', '0.00', '0.00', 
'0.42', '0.32', '0.11', '0.11\r\n'] 

人知道爲什麼正在發生,以及如何解決它?讓我知道是否有任何您需要的其他信息。此外,我願意爲這個問題提供一個更好的名字。

附錄: 對不起,我原本沒有把這個問題弄清楚。我仍然是python的初學者,也是Stack Overflow的新手;我不知道這是模棱兩可的,我的印象是我們應該儘可能簡潔地提出我們的問題,而不相關的細節是不可取的。

這是程序的目標,從文件中讀取行,每行是來自多個森林資源清單圖之一的樹的測量結果,並且對於每一行,在樹代表的樹上運行特定的物種方程該行中的前幾個值,然後將每個圖中所有樹的方程結果相加。

上面包含的代碼段I讀取了行中的第三個值,該行是該行中表示的樹的物種代碼,並將該行傳遞給包含該樹種特定方程的函數。

根據我已經得到的答案,這聽起來像是當上面的字典定義被讀取時,它會遍歷每一個列出的函數。我想要的東西基本上可以做選擇其他語言的情況。我有了使用字典和堆棧溢出的另一個Q & A的get方法的想法。

我只想在每次程序循環換行時運行匹配行列表中物種代碼的函數。我注意到發生的事情是,這本詞典似乎將線路傳遞給了錯誤的函數,因爲我在Pred_PSME函數中錯誤地捕獲了一些代碼,該函數在出現錯誤時打印行值(還有一個錯誤不斷彈出來計算Pred_PSME中的一個方程式值,這就是爲什麼我添加了調試代碼),並且它打印了上面包含的行。

也許我誤解了字典充滿了函數名稱的作品。我想我的問題是,編寫代碼將一行中的元素列表發送到符合liLn[2]中給出的物種代碼的函數?

在另一種語言,你將會對liLn[2]值使用select case,用每種情況下在字典中列出的關鍵之一,併爲每種情況下在其名稱中的值被列出的功能的命令的命令字典。

這裏是通向到詞典和多個上下文的字典的代碼:

def Main(): 
    srcf = open(bkp, 'r') 
    old_fcid = 0 
    li_fBQI = [] 
    i = 0 
    for line in srcf: 
     liLn = line.split(',') 
     liLn = stripquotes(liLn) 
     #Check if it's the first line, if so, jump to next line. 
     if len(liLn) < 2: continue 
     if HdrLine(liLn[:2]): continue 
     fcid = liLn[1] 
     #Check line fcid against last fcid 
     if old_fcid != 0 and fcid != old_fcid: 
      #Write the FCID BQI tallies to file 
      Write_fBQIs(old_fcid, li_fBQI) 
      #Reset FCID BQI tallies 
      li_fBQI = [] 
     old_fcid = fcid 
     #Calc BQI's for the tree 
     li_tBQI = BQI_Calc(liLn) 
     #Add tree BQI's to the FCID tallies 
     li_fBQI = AddBQI(li_tBQI, li_fBQI) 
     if i % 1000 == 0: print 'Finished line #' + str(i) 
     i += 1 
    #ADD: Write last FCID's BQI's to file 
    Write_fBQIs(old_fcid, li_fBQI) 
    srcf.close() 

def BQI_Calc(liLn): 
    di_eqns = {"PSME": Pred_PSME(liLn), "ABAM":Pred_ABAM(liLn), \ 
       "ABCO":Pred_Abies(liLn), "ABGR":Pred_Abies(liLn), \ 
       "ABLA":Pred_Abies(liLn), "ABMA":Pred_Abies(liLn), \ 
       "ABSH":Pred_Abies(liLn), "ABPR":Pred_ABPR(liLn), \ 
       "CADE27":Pred_Cedar(liLn), "CHLA":Pred_Cedar(liLn), \ 
       "CHNO":Pred_Cedar(liLn), "THPL":Pred_Cedar(liLn), \ 
       "LALY":Pred_LALY(liLn), "LAOC":Pred_LAOC(liLn), \ 
       "PIEN":Pred_PIEN(liLn), "PISI":Pred_PISI(liLn), \ 
       "PIAL":Pred_Pinus(liLn), "PIJE":Pred_Pinus(liLn), \ 
       "PIMO3":Pred_Pinus(liLn), "PICO":Pred_PICO(liLn), \ 
       "PILA":Pred_PILA(liLn), "PIPO":Pred_PIPO(liLn), \ 
       "TSHE":Pred_TSHE(liLn), "TSME":Pred_TSME(liLn), \ 
       "JUOC":Pred_JUOC(liLn), "TABR":Pred_TSHE(liLn), \ 
       "ALRU2":Pred_ALRU2(liLn), "ACCI":Pred_SMBGr(liLn), \ 
       "ACGL":Pred_SMBGr(liLn), "ACMA3":Pred_ACMA3(liLn), \ 
       "CONU4":Pred_ACMA3(liLn), "ALRH2":Pred_AACWGr(liLn), \ 
       "SASC":Pred_AACWGr(liLn), "SALIX":Pred_AACWGr(liLn), \ 
       "ARME":Pred_ARME(liLn), "BEPA":Pred_BEPA(liLn), \ 
       "BEPAC":Pred_BEPA(liLn), "CHCH7":Pred_CHCH7(liLn), \ 
       "FRLA":Pred_MHGr(liLn), "PREM":Pred_MHGr(liLn), \ 
       "PRVI":Pred_MHGr(liLn), "PRUNU":Pred_MHGr(liLn), \ 
       "LIDE3":Pred_LIDE3(liLn), "POBAT":Pred_POBAT(liLn), \ 
       "POTR5":Pred_POTR5(liLn), "QUCH2":Pred_QUCH2(liLn), \ 
       "QUGA4":Pred_QUGA4(liLn), "QUKE":Pred_QUKE(liLn), \ 
       "UMCA":Pred_UMCA(liLn)} 
    try: 
     li_pred = di_eqns.get(liLn[2]) 
    except: 
     print '\n\n', 50*'-', 'ERROR: Couldn\'t find equations for the spp',\ 
       'code:', liLn[2] 

    #Calc derivative quantities 

    .....and the function continues from there 

以下爲在字典中列出的功能的示例。Pred_PSME是我上面提到的那個。錯誤保存在幹樹皮(SB)計算存在的,所以我加了一些調試代碼,這就是我如何發現它發送的廉潔樹,這就是爲什麼我開始這個問題:

def Pred_PSME(liLn): 
    dbh = float(liLn[6]) 
    fol = exp(log(float(liLn[19])) + pqty(.0627, 123)) 
    lbr = exp((-3.6941 + 2.1382*log(dbh)) + pqty(.057, 123)) 
    dbr = exp((-3.529 + 1.7503*log(dbh)) + pqty(.079, 85)) 
    sw = exp(log(float(liLn[20])) + pqty(.0311, 99)) 
    try: 
     sb = exp(log(float(liLn[21])) + pqty(.0324, 99)) 
    except: 
     Badtree(liLn) 
     print dbh, liLn 
    ts = exp(-3.0396 + 2.5951*log(0.865 * mtd) + pqty(.0311, 99)) +\ 
     exp(-4.3103 + 2.4300*log(0.865 * mtd) + pqty(.0324, 99)) 
    br = lbr +dbr 
    agb_nf = br + sw + sb 
    agb = agb_nf + fol 
    return [fol, br, sw, sb, agb, agb_nf, ts] 

def Pred_ARME(liLn): 
    dbh = float(liLn[6]) 
    agb_nf = float(liLn[27]) + tvariate(57) * 1.23 * (1 + 1/60)**(1/2) 
    agb = agb_nf/(1 - folpct) 
    fol = agb - agb_nf 
    br = sw = sb = ts = 0 
    return [fol, br, sw, sb, agb, agb_nf, ts] 

希望這使事情更清晰。請讓我知道是否還有其他問題。順便說一句,當他們說「代碼味道」時,每個人都意味着什麼?另外,我在爲此網站設置文本格式方面遇到了一些麻煩。有沒有辦法在這個網站上標識一個代碼塊4個空格而不需要手動爲每一行添加4個空格?謝謝。

+0

我把你在這裏的字典(用字符串替換所有的字典值)並運行'print di_eqns.get('PIEN')'。我收到了'Pred_PIEN(liLn)'的迴應。你期待什麼結果? – 2011-03-20 07:52:08

+1

我覺得很奇怪,你的字典包含函數的*結果*而不是函數本身。 – 2011-03-20 08:11:12

+0

這個問題不一致。請提供真實字典的數據,而不是像「QUGA4」這樣的定義:Pred_QUGA4(liLn)。我們無法聞到Pred_UMCA(...)會返回什麼。否則這個問題值得-1。 – 2011-03-20 08:12:06

回答

3

我相信問題是,所有的Pred_XXXX(liLn)值 - 這似乎是函數調用 - 在di_eqns字典正在與他們的返回值替換時創建它 ...這當然會取決於在施工時liLn的價值,而不是在您撥打get()時。

類似以下內容會延遲對Pred_XXXX()函數的調用。基本上,它首先查找功能基於從文本文件列表中的第三項打電話,然後通過整個列表的功能:

di_eqns = {"PSME":Pred_PSME, "ABAM":Pred_ABAM, 
      "ABCO":Pred_Abies, "ABGR":Pred_Abies, 
      "ABLA":Pred_Abies, "ABMA":Pred_Abies, 
      "ABSH":Pred_Abies, "ABPR":Pred_ABPR, 
      "CADE27":Pred_Cedar, "CHLA":Pred_Cedar, 
      "CHNO":Pred_Cedar, "THPL":Pred_Cedar, 
      "LALY":Pred_LALY, "LAOC":Pred_LAOC, 
      "PIEN":Pred_PIEN, "PISI":Pred_PISI, 
      "PIAL":Pred_Pinus, "PIJE":Pred_Pinus, 
      "PIMO3":Pred_Pinus, "PICO":Pred_PICO, 
      "PILA":Pred_PILA, "PIPO":Pred_PIPO, 
      "TSHE":Pred_TSHE, "TSME":Pred_TSME, 
      "JUOC":Pred_JUOC, "TABR":Pred_TSHE, 
      "ALRU2":Pred_ALRU2, "ACCI":Pred_SMBGr, 
      "ACGL":Pred_SMBGr, "ACMA3":Pred_ACMA3, 
      "CONU4":Pred_ACMA3, "ALRH2":Pred_AACWGr, 
      "SASC":Pred_AACWGr, "SALIX":Pred_AACWGr, 
      "ARME":Pred_ARME, "BEPA":Pred_BEPA, 
      "BEPAC":Pred_BEPA, "CHCH7":Pred_CHCH7, 
      "FRLA":Pred_MHGr, "PREM":Pred_MHGr, 
      "PRVI":Pred_MHGr, "PRUNU":Pred_MHGr, 
      "LIDE3":Pred_LIDE3, "POBAT":Pred_POBAT, 
      "POTR5":Pred_POTR5, "QUCH2":Pred_QUCH2, 
      "QUGA4":Pred_QUGA4, "QUKE":Pred_QUKE, 
      "UMCA":Pred_UMCA} 

try: li_pred = di_eqns.get(liLn[2])(liLn) 

然而,如果沒有更多的信息關於你想要什麼來完成的,這是很難做出任何明確的建議...

+0

我想我們都檢測到相同的代碼異味,但沒有足夠的代碼來明確表示這是正在發生的事情。 – 2011-03-20 08:30:33

+0

我認爲這可能已經完成了... – cfwschmidt 2011-03-21 06:17:33

+0

所以,讓我直截了當。我以前的方式,每次定義字典時都會運行每個函數?現在字典只是指向函數,而函數只是與get方法和參數一起調用? – cfwschmidt 2011-03-21 06:33:33

2

如果di_eqns設置ONCE,然後在字典中的值將取決於在設置時間的liLn值。

如果di_eqns正在爲每個輸入記錄設置一次,那不是非常有效。創建一個包含49個條目的詞典是浪費的,但每個記錄可以容納一個。但在這種情況下它更糟糕:它評估所有49個函數調用,然後在僅計算一個結果時得到一個結果。這非常浪費。如果任何這些功能有副作用,例如他們改變了全球的狀態,除了總效率問題之外,你還有一個嚴重的邏輯問題。

我建議你設置你的字典一次,像這樣:

di_eqns = { 
    # for better legibility, arrange the following lines in alphabetical key order; 
    # then a duplicate key entry is easier to see. 
    "PSME": Pred_PSME, 
    "ABAM": Pred_ABAM, 
    "ABCO": Pred_Abies, 
    "ABGR": Pred_Abies, 
    # et cetera 
    } 

,併爲每個記錄做這樣的事情:

if debug: print "liLn", liLn 
handler_func = di_eqns[liLn[2]] # be prepared for KeyError here 
if debug: print "handler", repr(handler_func) 
li_pred = handler_func(liLn) 
if debug: print "li_pred", repr(li_pred) 

如果問題尚未消失,印刷報表應該幫助你找出原因。如果您需要更多幫助,您需要向我們展示PIEN功能的代碼和PSME功能的代碼,以及主線的代碼。

編輯更多代碼衛生:剛纔看了一下「從文本文件行」 ......與'0.32', '0.11', '0.11\r\n']結束了 - 看起來你應該使用CSV模塊讀取文件,而不是

for guff in f: 
    liLn = guff.split(',') 
+0

感謝您的有用評論和正確的答案之一。本來會給你接受的答案,但馬丁諾是最古老的。我已經對你的代碼進行了修改,所以它只定義了一次字典。至於csv的讀者,我正在嘗試學習如何使用它,但它有一些問題。顯然,我誤解了模塊的工作方式。在我做了一些研究之後,我可能不得不問另一個問題。 – cfwschmidt 2011-03-24 04:36:34