学习Python,有更好的写法吗?
我正在学习Python(2.7),为了测试我目前学到的知识,我写了一个温度转换器,可以把摄氏度转换成华氏度。我想知道我的代码是否可以写得更好,变得更快或者更符合Python的风格。另外,有人能告诉我if __name__ == '__main__': main()
这个写法有没有什么特别的名字吗?我只是好奇。
from sys import argv, exit # import argv and exit functions
def to_f(c): # Convert celsius to ferinheight
temp = (c * 9/5) + 32
return temp
def to_c(f): # Convert ferinheight to celsius
temp = (f - 32) * 5/9
return temp
def main():
args = argv[1:] # Creates an argument list omitting the omitting the [0] element
if len(argv) < 2: exit(1) # If less than two arguments
if args[0] == '-f': # If the first argument is -f
print args[1], 'ferinheight is', str(to_c(int(args[1]))), 'celsius'
elif args[0] == '-c': # If the first argument is -c
print args[1], 'celsius is', str(to_f(int(args[1]))), 'ferinheight'
else: exit(1)
if __name__ == '__main__':
main()
4 个回答
3
对Ned的回答有几个改进建议。
在Python2.7中,/
这个符号默认会把结果取整,所以你需要从__future__
里导入division
。否则像(c * 9/5) + 32
这样的计算总是会向下取整,这样会影响结果的准确性。
比如说,如果36摄氏度是96.8华氏度,返回97比返回96要好。
在convert
函数里其实不需要写返回语句。默认情况下,函数会返回None
。如果出现问题,你可以抛出一个异常。
现在更推荐使用"".format()
这种方式来格式化字符串。
另外一个改进是可以使用optparse
或者类似的工具来处理命令行参数,不过对于这么简单的程序来说,这可能有点多余。
from __future__ import division
import sys
def to_f(c): # Convert celsius to fahrenheit
return (c * 9/5) + 32
def to_c(f): # Convert fahrenheit to celsius
return (f - 32) * 5/9
def convert(args):
if len(args) != 2:
raise RuntimeError("List of two elememts required")
t = int(args[1])
if args[0] == '-f': # If the first argument is -f
print "{0} Fahrenheit is {1} Celsius".format(t, round(to_c(t)))
elif args[0] == '-c': # If the first argument is -c
print "{0} Celsius is {1} Fahrenheit".format(t, round(to_f(t)))
else:
raise RuntimeError("First element should be -c or -f")
if __name__ == '__main__':
sys.exit(convert(sys.argv[1:]))
4
if __name__ == '__main__':
这个写法是用在你写一个模块的时候,这个模块是打算被其他代码使用的,但你又想在里面加一些测试代码。
如果你直接运行这个模块,它就会执行这个 if
语句块里的内容。如果这个模块是从别的地方导入的,那它就不会执行里面的内容。
所以,我建议你保留这个 if __name__ == '__main__':
语句块,因为这样你可以在其他代码中做一些事情,比如:
from temp_conv import c_from_f
print c_from_f(73)
假设你把这个文件命名为 temp_conv.py。
11
import sys
def to_f(c): # Convert celsius to fahrenheit
return (c * 9/5) + 32
def to_c(f): # Convert fahrenheit to celsius
return (f - 32) * 5/9
def convert(args):
if len(args) < 2:
return 1 # If less than two arguments
t = args[1]
if args[0] == '-f': # If the first argument is -f
print "%s Fahrenheit is %s Celsius" % (t, to_c(int(t)))
return 0
elif args[0] == '-c': # If the first argument is -c
print "%s Celsius is %s Fahrenheit" % (t, to_f(int(t)))
return 0
else:
return 1
if __name__ == '__main__':
sys.exit(convert(sys.argv[1:]))
我做了以下几件事:
- 把
main()
的名字改成了convert()
- 明确地把参数传给
convert()
- 把调用
exit()
的地方改成返回值,并在主程序中调用exit()
。 - 你在检查
argv
的长度是否为2,但其实应该检查args
。 to_c
和to_f
这两个函数不需要一个temp
变量,直接返回结果就行了。- 虽然其他人说你可以把
main()
函数放在最上面,但使用if __name__
的方式更好,这样你可以导入这个模块并在其他代码中使用这些函数。 - 字符串格式化比在打印语句中混合字符串和数值要好看。
args[1]
出现得比较频繁,所以我把它简化成了t
。- 我更喜欢导入 sys,并使用
sys.argv
,比如这样。 - 我总是把依赖的语句放在新的一行,而不是写成
if blah: doit()
- 修正了“Fahrenheit”的拼写。