学习Python,有更好的写法吗?

4 投票
4 回答
1472 浏览
提问于 2025-04-16 01:08

我正在学习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()

http://pastebin.com/rjeNikDt

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

我做了以下几件事:

  1. main() 的名字改成了 convert()
  2. 明确地把参数传给 convert()
  3. 把调用 exit() 的地方改成返回值,并在主程序中调用 exit()
  4. 你在检查 argv 的长度是否为2,但其实应该检查 args
  5. to_cto_f 这两个函数不需要一个 temp 变量,直接返回结果就行了。
  6. 虽然其他人说你可以把 main() 函数放在最上面,但使用 if __name__ 的方式更好,这样你可以导入这个模块并在其他代码中使用这些函数。
  7. 字符串格式化比在打印语句中混合字符串和数值要好看。
  8. args[1] 出现得比较频繁,所以我把它简化成了 t
  9. 我更喜欢导入 sys,并使用 sys.argv,比如这样。
  10. 我总是把依赖的语句放在新的一行,而不是写成 if blah: doit()
  11. 修正了“Fahrenheit”的拼写。

撰写回答