Python 如何将此代码转换为函数程序(如范例中的那样)?

Python 如何将此代码转换为函数程序(如范例中的那样)?,python,functional-programming,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

我必须根据每单位的价格和数量来计算我的股票的总价值。我有以下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)
上面的代码获取此错误:

回溯(最近一次呼叫最后一次):
文件“python”,第30行,在
文件“python”,第28行,总计
TypeError:不可损坏的类型

有人能把我的代码改成功能性更强的编程版本吗?

如果说功能性编程,你指的是使用高阶函数和lambda:

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

出现错误是因为表达式
x[1://code>是一个字典,而不是键使用生成器表达式或列表/集合/字典理解功能非常强大:

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]
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]:

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

total = 0
for key in prices:
    total = total + prices[key]*stock[key]
print total
检查命令循环时,每次迭代都会改变的两件事是
total
,这本身就很好;和
key
,它源自
prices.keys()
。所以,我们需要这些东西

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

既然我们不能对total进行变异,那么让我们重写以下语句:

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

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

对于
furtnames
中的每个
key
,将运行总数增加
prices[key]*stock[key]

现在,这里有一个我无法解释的精神跳跃。提示是,
total
key
在循环的每次迭代中都在变化。现在我们可以忽略
total
(因为我不想把它与尾部递归优化进一步混淆)。对于功能样式,
将成为键的整个列表,
水果名

def totalRecur(fruitNames):
现在,让我们考虑一下基本情况。如果
价格
(和
股票
)为空怎么办?那么,总数将为零:

    if len(fruitNames) == 0:
        return 0
看起来不错。现在,如果零位只有一个项目呢

    key = fruitNames[0]
    return prices[key] * stock[key]
因为我们知道,
totalRecur([])
==0,所以我们可以说

    return prices[key] * stock[key] + totalRecur([])
而且,由于列表只有一个项目,我们知道
fruitNames[1://code>是空列表:

    return prices[key] * stock[key] + totalRecur(fruitNames[1:])
这将为您提供足够的信息,以便为
totalRecur

编写一个良好的定义。您可以使用a返回所需的值,而不会产生副作用,同时避免状态和突变(请参阅):


提供了灵感。

@GuillaumeJacquenot我不同意编辑。粘贴交互式解释器会话的输出在StackOverflow上很常见。删除In/Out行实际上会使它变得毫无意义,因为最后一行的工作方式与交互式会话中的工作方式类似。在Python中,递归通常是要避免的。功能性!=递归。??别那么戏剧化了。我只是说,如果您打算就如何用特定语言编写代码提供建议,您不应该鼓励使用通常会导致性能低下的结构。Python不是为递归而构建的,分配一个新的堆栈框架会带来很多开销,并且没有尾部调用优化。还有一个递归限制。有些情况下,比如在你知道不是很深的树上行走,递归实现的简单性可能会超过非递归实现!我为我含糊不清的语气道歉。我一点也不想戏剧化。我同意你的意见。我一直认为函数意味着大量使用递归。然后我想了想你说的话,还记得我在Python3中使用大量尾部递归时遇到的一些麻烦,当超过最大递归深度时,仍然会发出错误。不,不,我道歉。我误读了你的评论,说“StackOverflow[该网站]糟透了”。无论如何,我得到的错误信息是错误的。它应该是
运行时错误:超过最大递归深度
def total(prices, stock):
    return sum([p * stock[k] for k, p in prices.items() if k in stock])

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