2016-12-28 36 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提供了灵感。

相关问题