我刚刚编写了第一个代码,基本上是一个计算器。请对其评分并提出改进建议(请记住,我是初学者)。

import math

#Returns the sum of num1 and num2
def add(num1, num2):
    return num1 + num2

import math

#Returns the difference between num1 and num2
def sub(num1, num2):
    return num1 - num2

#Returns product of num1 and num2
def mul(num1, num2):
    return num1 * num2

#Returns the quotient of num1 and num2
def div(num1, num2):
    return num1 / num2

#Returns the result of num1 to the power of num2    
def exp(num1, num2):
    return num1 ** num2

#Returns the square of num1
def sqrt(num1):
    return num1**2

#Returns the value of pi
def pi():
    pi = 3.14159265
    return pi

#Returns the value of num1 multiplied with pi
def mulpi(num1):
    pi = 3.14159265
    return num1*pi


def main():
    operation = input("What do you want to do? (+,-,*,/,exp,pi,_pi,sqrt)")
    if(operation != '+' and operation != '-' and operation != '*' and operation != '/' and operation != 'exp' and operation != '_pi' and operation != 'sqrt' and operation != 'pi'):
        #Invalid Operation
        print("YOU MUST ENTER A VALID OPERATION")
    elif(operation == 'pi'):
        print(pi()) 
    elif(operation == '_pi' or 'sqrt'):
        var1 = int(input("enter number: "))
        if(operation == '_pi'):
            print(mulpi(var1))
        elif(operation == 'sqrt'):
            print(sqrt(var1))
    else:
        var1 = int(input("enter num1: "))
        var2 = int(input("enter num2: "))
        if(operation == '+'):
            print (add(var1, var2))
        elif(operation == '*'):
            print(mul(var1, var2))
        elif(operation == '-'):
            print(sub(var1, var2))
        elif(operation == 'exp'):
            print(exp(var1, var2))
        else:
            print(div(var1, var2))

main()


评论

尽管它对您的情况有帮助(入门级,熟悉数据类型等),但是注释通常不能告诉您一段代码中完成了什么,而是为什么要这样编写。通常,经验丰富的编码人员会弄清楚在特定代码块中会发生什么,但他们无法弄清楚为什么要这样做(因为总是有多种方式,而第二种方式显然是错误的)。 br />
但是,这些注释看起来像文档字符串。 (应该写在函数内部和三引号中)。文档字符串确实说明了什么代码,因为它们是API参考

您应该将def sqrt(num1)更改为def sqr(num1),因为sqrt是数学模块中的平方根函数

#1 楼

输入验证

当用户输入整数时,您绝对不会进行输入验证。如果用户输入非整数值(例如foobar),则代码将因ValueError而崩溃。获取用户输入的正确方法是使用try / except块,如下所示:

try:
    var1 = int(input( ... ))
    var2 = int(input( ... ))

    ...
except ValueError:
    print("Invalid input!")
    ... 


通过这样做,可以确保您的程序不会输入无效时崩溃。


输入映射

现在,您正在链接if / elif / else语句以检查用户输入。这不是执行此操作的最佳方法。相反,您可以为可能的输入创建一个字典映射,如下所示:

像这样:

OPERATIONS = {
    "+": add,
    "-": sub,
    ...
}


而不是一连串if / elif / else语句,这使您的代码更清晰,更易于阅读。 />
使用mathoperator


绝对没有理由定义自己的数学函数,只是为了可以在字典映射中使用它们,您应该使用而是使用mathoperator模块。这些都提供内置函数(例如addsub)或值(例如\ $ \ pi \ $或\ $ e \ $)。 br />

if / elif / else语句之间不需要括号。可以这样写:

operation = input( ... )
if operation in OPERATIONS:
    OPERATIONS[operation](var1, var2)
else:
    print("Invalid operation!")



您应该使用if __name__ == "__main__"保护罩。这样可以确保如果将代码导入到另一个文件中,则某些代码将不会运行。这意味着该函数将在此处调用:

if condition:
    ...


应该变成这样:两次导入math。导入后,其功能和变量已经填充了文件的名称空间。

最后,如果您要为函数编写注释(在这种情况下,注释将毫无用处),则应改用文档字符串。一个典型的文档字符串看起来像这样:



#2 楼

以下是一些评论:


阅读PEP 257,其中介绍了文档字符串。文档字符串是在Python中记录函数的首选方式,而不是在定义上方添加注释。

您需要两次导入math模块。您只需要执行一次,按照PEP 8(Python样式指南),它们应该放在文件的顶部。 br />

在以下两个函数中:

#Returns the value of pi
def pi():
    pi = 3.14159265
    return pi

#Returns the value of num1 multiplied with pi
def mulpi(num1):
    pi = 3.14159265
    return num1*pi


您正在硬编码pi的值,而忽略了定义的函数专门用于查找pi。如果要执行此操作,最好将pi声明为文件顶部的常量。但是更好的方法是使用数学模块中的pi版本:

>>> import math
>>> math.pi
3.141592653589793



此函数的命名似乎不正确:

#Returns the square of num1
def sqrt(num1):
    return num1**2


该名称通常与数字的平方根相关联,而不与平方相关。当您添加更多操作时:

if(operation != '+' and operation != '-' and operation != '*' and operation != '/' and operation != 'exp' and operation != '_pi' and operation != 'sqrt' and operation != 'pi'):


最好定义一个操作列表,然后检查它是否在该列表内。另外,您可以将其附加到帮助热线:我。

没有输入验证。我可以输入非数字,怪异的数字或没有意义的值。例如,如果我尝试除以零,会发生什么?

您选择操作的逻辑并不像您认为的那样起作用。特别是,此行:

operations = ['+', '-', '*', '/', 'exp', 'pi', '_pi', 'sqrt']
operation = input("What do you want to do? ({ops})".format(','.join(operations)))
if operation not in operations:
    ...


将始终执行。原因是Python将其分解为(括号我的):

更好的方法是

 elif(operation == '_pi' or 'sqrt'):


与其选择基于一系列嵌套if语句的操作,不如使用将操作字符串转换为运算符的dict。这将使以后添加新操作变得更容易。


#3 楼

Main

首先,您最好使用main。
但是如果我不小心导入了程序,
我可能不希望它运行。
为了安全起见,您可以将呼叫包装在if __name__ == '__main__':

如果您的程序被称为“ calc.py”,则将运行以下程序。

import calc


使用if __name__ == '__main__':时,您的代码将不会运行。
但是我仍然可以执行calc.mul(1, 2)。 > Python对函数友好。它使您可以像传递变量一样将它们传递出去。

def my_func():
    return 1

my_new_func = my_func
print(my_new_func) # 1


乍一看似乎毫无意义,但是结合字典和列表,您可以做一些很酷的事情。

字典就像一个列表,
它既可以有字符串,也可以有整数作为键。

my_dict = {'foo': 'bar'}
print(my_dict['foo']) # bar


现在进入魔术!

如果我们将这两件事结合在一起,那么我们可以删除多少条if语句? />但是您将如何使用它呢?

您可以更改main的else来包含它。


用户输入错误

您的main的else语句看起来不错,但仍然存在问题。

my_functions = {
    '+': add,
    '-': sub,
    # etc
}

print(my_functions['+'](2, 3)) # 5


这实际上很容易修改。

首先,如果您不知道tryexcept语句是什么。 >这将始终打印'您不能被零除。'。

我们如何在您的程序中使用它来修复以上问题?

var1 = int(input("enter num1: "))
var2 = int(input("enter num2: "))
print(my_functions[operation](var1, var2))


这是一个非常基本的版本。
您希望将其更改为更安全并循环。

br />
现在主体的else更简单。

enter num1: 43
enter num2: 51q
# program exits.



移除if

我认为拥有如此大的首字母int(input())并不是一个好主意。 'exp','_ pi','sqrt'和'pi'。
然后它将继续检查是否为'pi'。

我认为这有点太多了。而我将其命名为if

要使转换变得容易,您可以制作更多词典!
但是在此之前,您应该了解带有词典的else。 >
try:
    1 / 0
except:
    print("you can't divide by zero.")


我将如何实现字典和if语句?
您可以拥有'constants','singletons'和'duets'的字典。
然后,“ singletons”将是“ _pi”和“ sqrt”的字典。

易于实现。

try:
    return int(input("enter num2: "))
except:
    print('Enter valid numbers.')
    return 1


现在我们可以使用in来检查它们是否包含该功能。

def ask(question, fn=int):
    while True:
        answer = input(question)
        try:
            return fn(answer)
        except ValueError:
            print('\r\b\r')



Lambda

最后,如果要坚持建议使用in dict之类的功能,
我建议以其他方式进行操作。

所以我将使用mul

var1 = ask("enter num1: ")
var2 = ask("enter num2: ")
print(my_functions[operation](var1, var2))


请不要执行上述操作。 br />改用lambda

这样很好,因为我们可以在字典中创建所有函数。

my_dict = {'foo': 'bar'}
print('foo' in my_dict) # True
print('bar' in my_dict) # False
print('baz' in my_dict) # False



总而言之,对于第一个程序,这非常好。

但是,最终用户是您最大的敌人,并且会尝试破坏您的程序。
您可以将其缩小一些。

functions = {
    'constants': {
        'pi': pi
    },
    'singletons': {
        '_pi': mulpi,
        # etc
    },
    # etc
}


最后,它仍然会在def上中断,但是我敢肯定,您现在可以解决这个问题。

#4 楼

其他人已经提出了很多要点,但是我认为您缺少的一个关键的简单功能是保留价值。如果您有一个持久的num变量,那么您只需在计算器中保留循环和链接操作即可。这使它更有用,并且可以从代码中删除重复项。底部,适用于所有情况。现在,您可以更改结果的显示方式,而无需在多个位置进行编辑。