2016-11-08 91 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

相關問題