我如何将此代码转换为功能程序(如范例中)?

时间:2016-12-28 19:48:10

标签: python functional-programming

我必须根据每单位价格和单位数计算我的库存总价值。我在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

有人可以将我的代码更正为更具功能性的编程版本吗?

5 个答案:

答案 0 :(得分:1)

如果通过函数式编程,你的意思是使用更高阶函数和lambdas:

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

您收到错误,因为表达式x[1:]是字典,而不是键

答案 1 :(得分: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]:

答案 2 :(得分:1)

首先,让我们看一下命令式循环:

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

检查命令循环,每次迭代改变的两件事是total,这本身就很好,而key来自prices.keys()。所以,我们需要那些东西。

让我们尝试用自然语言重写命令循环。我会选英语。对于key [或者应该是prices]中的每个prices.keys(),请将总数增加prices[key]*stock[key]

由于我们不能改变总数,所以让我们改写声明:

对于key中的每个prices.keys(),将运行总计增加prices[key]*stock[key]

而且,由于prices.keys()是水果的名字,让我们再写一次:

对于key中的每个fruitNames,将运行总计增加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的好定义。

答案 3 :(得分: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提供了灵感。

答案 4 :(得分:-1)

browserHistory.push({ pathname: npathname, query: {
    checkin : checkin,
    checkout : checkout,
    managed_by : 'Owner',
    managed_by : 'Manager',
} });