Python 如何将此代码转换为函数程序(如范例中的那样)?
我必须根据每单位的价格和数量来计算我的股票的总价值。我有以下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
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