2016-12-28 47 views
1

我必須根據單位價格和單位數來計算我股票的總價值。我有下面的代碼在Python:如何將此代碼轉換爲功能程序(如範例中)?

prices = { 
    "banana" : 4, 
    "apple" : 2, 
    "orange" : 1.5, 
    "pear" : 3, 
} 
stock = { 
    "banana" : 6, 
    "apple" : 0, 
    "orange" : 32, 
    "pear" : 15, 
} 

for key in prices: 
    print key 
    print "price: %s" % prices[key] 
    print "stock: %s" % stock[key] 

total = 0 
for key in prices: 
    total = total + prices[key]*stock[key] 
print total 

而且我試過用這種替代的最後一個塊將其轉換爲一個功能更強大的程序:

def total(x): 
    if len(x) == 1: 
     return prices[prices.keys()[0]]*stock[prices.keys()[0]] 
    else: 
     return prices[prices.keys()[0]]*stock[prices.keys()[0]] + total(x[1:]) 

print total(prices) 

上面的代碼得到這個錯誤:

Traceback (most recent call last): 
    File "python", line 30, in <module> 
    File "python", line 28, in total 
TypeError: unhashable type 

有人可以請更正我的代碼更多的功能編程版本?

回答

1

首先,讓我們看看勢在必行循環:

total = 0 
for key in prices: 
    total = total + prices[key]*stock[key] 
print total 

檢查勢在必行環,兩件事情正在改變每個迭代的total,這是很好的本身,並key,從prices.keys()起源。所以,我們需要這些東西。我們試着用自然語言重寫命令循環。我會選擇英語。對於prices [或者應該是prices.keys()]中的每個key,將總數增加prices[key]*stock[key]

既然我們不能總髮生變異,讓我們重寫聲明:

對於每個keyprices.keys(),由prices[key]*stock[key]增加跑的總。

而且,由於prices.keys()是水果的名字,讓我們再次把它寫:

對於每個keyfruitNames,由prices[key]*stock[key]增加跑的總。

現在,這是一個心理跳躍,我不能解釋。提示是totalkey通過循環的每次迭代而改變。我們現在可以忽略total(因爲我不打算將這個進一步與尾遞歸優化混淆)。對於功能樣式,key成爲密鑰的完整列表,fruitNames

def totalRecur(fruitNames): 

現在,我們來考慮一下基本情況。如果prices(和stock)是空的呢?那麼,總數將爲零:

if len(fruitNames) == 0: 
     return 0 

這看起來很好。現在,如果在位置零處只有一個項目呢?

key = fruitNames[0] 
    return prices[key] * stock[key] 

因爲我們知道,totalRecur([]) == 0,我們可以改爲說

return prices[key] * stock[key] + totalRecur([]) 

而且,由於只列出了一個項目,我們知道fruitNames[1:]是空列表:

return prices[key] * stock[key] + totalRecur(fruitNames[1:]) 

這應該給你足夠的信息來寫出一個好的定義totalRecur

+1

在Python中通常要避免遞歸。功能!=遞歸。 –

+0

哦,對,'StackOverflowError'很糟糕。 – LexieHankins

+1

??停止如此戲劇化。我只是簡單地指出,如果您要就如何使用特定語言編寫代碼提供建議,則不應鼓勵使用通常會導致性能較差的構造。 Python不是爲遞歸而構建的,分配一個新的棧幀有很多開銷,並且沒有tail-call優化。還有一個遞歸限制。有些情況下,比如走在一棵樹上,你知道它並不是很深,在這種情況下,遞歸實現的簡單性可能會超過非遞歸實現。 –

1

如果函數式編程,您可以通過使用高階函數和lambda表達式的意思是:

sum(map(lambda k, v: v * stock[k], prices.items())) 

因爲表達式x[1:]是一本字典,而不是一個關鍵

-1
def total(stock): 
    return sum([v*prices[k] for k,v in stock.iteritems()]) #.iteritems() is a built in method for dicts. it returns key, value pairs 
                  #same as i, dict[i] 
1

使用發電機你得到一個錯誤表達式或列表/集/字典解析功能非常強大:

In [1]: prices = { 
    ...:  "banana" : 4, 
    ...:  "apple" : 2, 
    ...:  "orange" : 1.5, 
    ...:  "pear" : 3, 
    ...: } 
    ...: stock = { 
    ...:  "banana" : 6, 
    ...:  "apple" : 0, 
    ...:  "orange" : 32, 
    ...:  "pear" : 15, 
    ...: } 
    ...: 

In [2]: total_value = sum(stock[k]*prices[k] for k in stock) 

In [3]: total_value 
Out[3]: 117.0 

In [4]: 
+0

@GuillaumeJacquenot我不同意編輯。在StackOverflow上粘貼交互式解釋器會話的輸出是很常見的。刪除In/Out行實際上使其變得無意義,因爲最後一行只能在交互式會話中像*那樣工作* –

1

可以使用dict comprehension返回所需的值無副作用,避免國家和變異太(見Functional Programming):

def total(prices, stock): 
    return sum([p * stock[k] for k, p in prices.items() if k in stock]) 

>>> total(prices, stock) 
>>> 117.0 

This answer提供了靈感。