我刚写了一个小小的<->厘米转换程序。虽然我知道我已经以一种相当愚蠢的方式做了一些事情,而且它可以改进,但它的工作还是很好的。
def conversion():
try: amount = int(raw_input("Please enter the value: "))
except ValueError:
print "Please specify a valid amount."
return conversion()
answer = raw_input("Please choose between converting FROM kilograms/pounds: ")
if answer == "kilograms":
return amount * 2.2
elif answer == "pounds":
return amount / 1.45
else:
print "Please choose between kilograms and pounds."
restart = raw_input("Try again? ")
if restart == "yes":
return conversion()
elif restart == "y":
return conversion()
else:
print "Okay, bye."
return
print conversion()发布于 2011-04-18 15:38:52
第一点是关注点的分离:每个实体(函数,类…)应该只负责一项任务(讽刺的是,打印结果除外)。
在您的代码中,一个函数(conversion)负责一切。试着把不同的问题分开:
当然,对于这样一个非常小的项目,其结果几乎肯定会更大。但它也将更加清晰和容易推广。
接下来是递归的使用。我非常喜欢递归(更多!)作为下一个程序员,但是在您的例子中,一些循环不会影响可读性。
第三点,应该避免神奇常数。您对转换因子2.2和1.45的使用是无害的,但它很快就会成为大型程序中的一个问题。使用正确命名的常量代替。
发布于 2011-04-18 19:14:31
在这种情况下不要使用递归。Python不优化尾递归,经过长时间会话后,脚本可以显示您的RuntimeError: maximum recursion depth exceeded。
在这种情况下不要使用浮点算法。将十进制算术与小数模块结合使用。例如:
>>> 100 * 2.2
220.00000000000003
>>> from decimal import Decimal
>>> Decimal("100") * Decimal("2.2")
Decimal('220.0')分裂逻辑和表示。目前,无法将此转换器与Web一起使用,也无法将其用作更大程序的库。例如,您可以从下面这样的低级函数开始:
def kilograms_to_pounds(amount):
return amount * Decimal("2.2")
def pounds_to_kilograms(amount):
return amount / Decimal("1.45")然后您可以创建这样的前端函数:
converters = {
("kilograms", "pounds"): kilograms_to_pounds,
("pounds", "kilograms"): pounds_to_kilograms,
}
def convert(amount, from_, to):
c = converters.get((from_, to))
if c is None:
raise ValueError("converter not found")
return c(amount)
>>> convert(Decimal("100"), "pounds", "kilograms")
Decimal('68.96551724137931034482758621')稍后,您可以添加这样的别名(或作为函数装饰符):
aliases = {
"kg": "kilograms",
"lb": "pounds",
...
}
def convert(amount, from_, to):
from_ = aliases.get(from_, from_)
to = aliases.get(to, to)
c = converters.get((from_, to))
if c is None:
raise ValueError("converter not found")
return c(amount)
>>> convert(Decimal("100"), "lb", "kg")
Decimal('68.96551724137931034482758621')使用此体系结构,您以后可以将其他转换器添加到库中,并且只需要从UI循环调用convert()函数。
我也不喜欢你的UI。例如,如果我需要将10个值从公斤转换为磅,我需要输入值,然后输入“公斤”。通过添加模式到您的转换器,您可以节省我10行。例如,用户首先输入“公斤到磅”,这种转换模式存储并显示在提示符中。然后,用户可以输入将从公斤转换为磅的值。以后,用户可以通过输入“磅到公斤”来改变转换模式。
发布于 2011-04-18 15:40:09
我不建议你用这种方式构造这个应用程序。一个更干净的解决方案(IMHO)是将值输入到脚本的参数中,这样就可以使用./convert --inch 5.2或./convert --cm 5.2调用它。另外,要将所有功能合并到一个函数中并不是一个好做法,您至少应该将输入/输出和函数分开。
不过,我确实做了自己的版本,在功能上应该是相当平等的,尽管我怀疑有一些不同之处。这不是一个更好的解决方案..。只是不一样。
#!/usr/bin/python2
def convert(value, frm):
try:
amount = int(value)
except:
throw Exception("Value is not an numeric")
return amount * 2.2 if frm == "kilograms" else (1/1.45) if frm == "pounds" else throw Exception("Can only convert from kilograms or pounds")
def ask_user():
while(True):
amount = raw_input("Please enter the value: ");
frm = raw_input("Please choose between converting FROM kilograms/pounds: ")
try:
result = convert(amount, frm)
print "The result is " + result + " " + "pounds" if frm == "kilograms" else "kilograms"
except Exception as e:
print e
print "Please try again"
continue
restart = raw_input("Try again? ");
if restart[0] == 'y':
continue
else:
print "Okey, bye."
break
if __name__ = '__main__': # This row is to be able to import the file without the question being asked on import.
ask_user()https://codereview.stackexchange.com/questions/1952
复制相似问题