2016-11-08 57 views
0

下面的两个函数对两个整数执行算术运算并返回一个整数结果。在这种情况下是不是使用eval()和字典更好的方法?

我听说很多关于eval()真的很糟糕,因为它可能会导致很多问题。但看看我在下面写的代码,看起来eval()可以排除许多代码行,对吧?

def dict_calculate(operation, num1, num2): 
    operations = {'add': '+', 'subtract': '-', 'multiply': '*', 'divide': '//'} 
    return eval(str(num1) + operations[operation] + str(num2)) 

def conditional_calculate(operation, num1, num2): 
    if operation == 'add': 
     return num1 + num2 
    if operation == 'subtract': 
     return num1 - num2 
    if operation == 'multiply': 
     return num1 * num2 
    if operation == 'divide': 
     return num1 // num2 

if __name__ == "__main__": 
    x = 10 
    y = 5 

    print(str(dict_calculate('add', x, y)) + ', ', end='') 
    print(str(dict_calculate('subtract', x, y)) + ', ', end='') 
    print(str(dict_calculate('multiply', x, y)) + ', ', end='') 
    print(str(dict_calculate('divide', x, y))) 

    print(str(conditional_calculate('add', x, y)) + ', ', end='') 
    print(str(conditional_calculate('subtract', x, y)) + ', ', end='') 
    print(str(conditional_calculate('multiply', x, y)) + ', ', end='') 
    print(str(conditional_calculate('divide', x, y))) 

输出是两种功能

15, 5, 50, 2 
15, 5, 50, 2 

是不是最好的eval在这种情况下使用相同的?如果没有,是否有比eval()更好的方法来实现相同类型的代码效率?

非常感谢。

+3

你会正确过滤/验证所有的用户输入,以确保您'没有评估出具有不良副作用的东西......? – deceze

+1

查看['operator' module](https://docs.python.org/3/library/operator.html),或者为每个操作符定义您自己的函数。函数只是对象,你可以将它们存储在字典中。 –

+0

@deceze我明白你的意思......有没有什么办法可以避免这种情况,而不用写很多if语句? – BuggyLemon

回答

5

你可以这样做:

import operator 
def dict_calculate(operation, num1, num2): 
    operations = {'add': operator.add, 
        'subtract': operator.sub, 
        'multiply': operator.mul, 
        'divide': operator.floordiv} 
    return operations[operation](num1, num2) 

如果你不想导入另一个模块,你可以这样做:

def dict_calculate(operation, num1, num2): 
    operations = {'add': '__add__', 
        'subtract': '__sub__', 
        'multiply': '__mul__', 
        'divide': '__floordiv__'} 
    return getattr(num1, operations[operation])(num2) 
+0

我即将发布类似的答案。这比使用'eval()'更安全,因为在这里你将可能的操作减少为实际的算术操作,而不是让用户通过使用eval来做_anything_(如删除/修改文件等) – Guillaume

+2

令人惊叹的是,我猜这里的智慧就是在字典中使用助手函数,而不是直接评估字符串版本的操作符。非常感谢。 – BuggyLemon

+1

如果你保留原来的运算符名称而不是更多或更少的任意别名,你甚至可以执行'getattr(运算符,操作)(num1,num2)'... – deceze

相关问题