亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

利用Python+eval函數(shù)構(gòu)建數(shù)學(xué)表達(dá)式計(jì)算器

 更新時(shí)間:2022年09月08日 12:43:42   作者:云朵君  
Python?中的函數(shù)eval()?是一個(gè)非常有用的工具。在本文中,云朵君將和大家一起學(xué)習(xí)?eval()?如何工作,以及如何在?Python?程序中安全有效地使用它,需要的可以參考一下

Python 中的函數(shù)eval()?是一個(gè)非常有用的工具,在前期,我們一起學(xué)習(xí)過(guò)該函數(shù)點(diǎn)擊查看:Python eval 函數(shù)動(dòng)態(tài)地計(jì)算數(shù)學(xué)表達(dá)式?。盡管如此,我們?cè)谑褂弥?,還需要考慮到該函數(shù)的一些重要的安全問(wèn)題。在本文中,云朵君將和大家一起學(xué)習(xí) eval() 如何工作,以及如何在 Python 程序中安全有效地使用它。

eval() 的安全問(wèn)題

本節(jié)主要學(xué)習(xí) eval() 如何使我們的代碼不安全,以及如何規(guī)避相關(guān)的安全風(fēng)險(xiǎn)。

eval() 函數(shù)的安全問(wèn)題在于它允許你(或你的用戶)動(dòng)態(tài)地執(zhí)行任意的Python代碼。

通常情況下,會(huì)存在正在讀(或?qū)懀┑拇a不是我們要執(zhí)行的代碼的情況。如果我們需要使用eval()來(lái)計(jì)算來(lái)自用戶或任何其他外部來(lái)源的輸入,此時(shí)將無(wú)法確定哪些代碼將被執(zhí)行,這將是一個(gè)非常嚴(yán)重的安全漏洞,極易收到黑客的攻擊。

一般情況下,我們并不建議使用 eval()。但如果非要使用該函數(shù),需要記住根據(jù)經(jīng)驗(yàn)法則:永遠(yuǎn)不要 用 未經(jīng)信任的輸入 來(lái)使用該函數(shù)。這條規(guī)則的重點(diǎn)在于要弄清楚我們可以信任哪些類型的輸入。

舉個(gè)例子說(shuō)明,隨意使用eval()?會(huì)使我們寫的代碼漏洞百出。假設(shè)你想建立一個(gè)在線服務(wù)來(lái)計(jì)算任意的Python數(shù)學(xué)表達(dá)式:用戶自定義表達(dá)式,然后點(diǎn)擊運(yùn)行?按鈕。應(yīng)用程序app獲得用戶的輸入并將其傳遞給eval()進(jìn)行計(jì)算。

這個(gè)應(yīng)用程序app將在我們的個(gè)人服務(wù)器上運(yùn)行,而那些服務(wù)器內(nèi)具有重要文件,如果你在一個(gè)Linux 操作系統(tǒng)運(yùn)行命令,并且該進(jìn)程有合法權(quán)限,那么惡意的用戶可以輸入危險(xiǎn)的字符串而損害服務(wù)器,比如下面這個(gè)命令。

"__import__('subprocess').getoutput('rm –rf *')"

上述代碼將刪除程序當(dāng)前目錄中的所有文件。這簡(jiǎn)直太可怕了!

注意: __import__()?是一個(gè)內(nèi)置函數(shù),它接收一個(gè)字符串形式的模塊名稱,并返回一個(gè)模塊對(duì)象的引用。__import__()? 是一個(gè)函數(shù),它與導(dǎo)入語(yǔ)句完全不同。我們不能使用 eval() 來(lái)計(jì)算一個(gè)導(dǎo)入語(yǔ)句。

當(dāng)輸入不受信任時(shí),并沒有完全有效的方法來(lái)避免eval()?函數(shù)帶來(lái)的安全風(fēng)險(xiǎn)。其實(shí)我們可以通過(guò)限制eval()的執(zhí)行環(huán)境來(lái)減少風(fēng)險(xiǎn)。在下面的內(nèi)容中,我們學(xué)習(xí)一些規(guī)避風(fēng)險(xiǎn)的技巧。

限制globals和locals

可以通過(guò)向 globals 和 locals 參數(shù)傳遞自定義字典來(lái)限制 eval()? 的執(zhí)行環(huán)境。例如,可以給這兩個(gè)參數(shù)傳遞空的字典,以防止eval()訪問(wèn)調(diào)用者當(dāng)前范圍或命名空間中的變量名。

# 避免訪問(wèn)調(diào)用者當(dāng)前范圍內(nèi)的名字
>>> x = 100
>>> eval("x * 5", {}, {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'x' is not defined

如果給 globals 和 locals 傳遞了空的字典({}?),那么eval()?在計(jì)算字符串 "x * 5 "? 時(shí),在它的全局名字空間和局部名字空間都找不到名字x?。因此,eval()將拋出一個(gè)NameError。

然而,像這樣限制 globals 和 locals 參數(shù)并不能消除與使用 Python 的 eval() 有關(guān)的所有安全風(fēng)險(xiǎn),因?yàn)槿匀豢梢栽L問(wèn)所有 Python 的內(nèi)置變量名。

限制內(nèi)置名稱的使用

函數(shù) eval()? 會(huì)在解析 expression 之前自動(dòng)將 builtins? 內(nèi)置模塊字典的引用插入到 globals 中。使用內(nèi)置函數(shù) __import__()  來(lái)訪問(wèn)標(biāo)準(zhǔn)庫(kù)和在系統(tǒng)上安裝的任何第三方模塊。這還容易被惡意用戶利用。

下面的例子表明,即使在限制了 globals 和 locals 之后,我們也可以使用任何內(nèi)置函數(shù)和任何標(biāo)準(zhǔn)模塊,如 math 或 subprocess。

>>> eval("sum([5, 5, 5])", {}, {})
15
>>> eval("__import__('math').sqrt(25)", {}, {})
5.0
>>> eval("__import__('subprocess').getoutput('echo Hello, World')", {}, {})
'Hello, World'

我們可以使用 __import__() 來(lái)導(dǎo)入任何標(biāo)準(zhǔn)或第三方模塊,如導(dǎo)入 math 和 subprocess 。因此 可以訪問(wèn)在 math、subprocess 或任何其他模塊中定義的任何函數(shù)或類?,F(xiàn)在想象一下,一個(gè)惡意的用戶可以使用 subprocess 或標(biāo)準(zhǔn)庫(kù)中任何其他強(qiáng)大的模塊對(duì)系統(tǒng)做什么,那就有點(diǎn)恐怖了。

為了減少這種風(fēng)險(xiǎn),可以通過(guò)覆蓋 globals 中的 "__builtins__?" 鍵來(lái)限制對(duì) Python 內(nèi)置函數(shù)的訪問(wèn)。通常建議使用一個(gè)包含鍵值對(duì) "__builtins__:{}" 的自定義字典。

>>> eval("__import__('math').sqrt(25)", {"__builtins__": {}}, {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name '__import__' is not defined

如果我們將一個(gè)包含鍵值對(duì) "__builtins__: {}?" 的字典傳遞給 globals,那么 eval()? 就不能直接訪問(wèn) Python 的內(nèi)置函數(shù),比如 __import__()。

然而這種方法仍然無(wú)法使得 eval() 完全規(guī)避風(fēng)險(xiǎn)。

限制輸入中的名稱

即使可以使用自定義的 globals? 和 locals? 字典來(lái)限制 eval()?的執(zhí)行環(huán)境,這個(gè)函數(shù)仍然會(huì)被攻擊。例如可以使用像""、"[]"、"{}"或"() "?來(lái)訪問(wèn)類object以及一些特殊屬性。

>>> "".__class__.__base__
<class 'object'>
>>> [].__class__.__base__
<class 'object'>
>>> {}.__class__.__base__
<class 'object'>
>>> ().__class__.__base__
<class 'object'>

一旦訪問(wèn)了 object,可以使用特殊的方法 `.__subclasses__()`來(lái)訪問(wèn)所有繼承于 object 的類。下面是它的工作原理。

>>> for sub_class in ().__class__.__base__.__subclasses__():
...     print(sub_class.__name__)
...
type
weakref
weakcallableproxy
weakproxy
int
...

這段代碼將打印出一個(gè)大類列表。其中一些類的功能非常強(qiáng)大,因此也是一個(gè)重要的安全漏洞,而且我們無(wú)法通過(guò)簡(jiǎn)單地限制 eval() 的避免該漏洞。

>>> input_string = """[
...     c for c in ().__class__.__base__.__subclasses__()
...     if c.__name__ == "range"
... ][0](10 "0")"""
>>> list(eval(input_string, {"__builtins__": {}}, {}))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

上面代碼中的列表推導(dǎo)式對(duì)繼承自 object? 的類進(jìn)行過(guò)濾,返回一個(gè)包含 range? 類的 list?。第一個(gè)索引([0]?)返回類的范圍。一旦獲得了對(duì) range? 的訪問(wèn)權(quán),就調(diào)用它來(lái)生成一個(gè) range? 對(duì)象。然后在 range? 對(duì)象上調(diào)用 list(),從而生成一個(gè)包含十個(gè)整數(shù)的列表。

在這個(gè)例子中,用 range? 來(lái)說(shuō)明 eval()? 函數(shù)中的一個(gè)安全漏洞?,F(xiàn)在想象一下,如果你的系統(tǒng)暴露了像 subprocess.Popen 這樣的類,一個(gè)惡意的用戶可以做什么?

我們或許可以通過(guò)限制輸入中的名字的使用,從而解決這個(gè)漏洞。該技術(shù)涉及以下步驟。

  • 創(chuàng)建一個(gè)包含你想用eval()使用的名字的字典。
  • 在eval? 模式下使用compile() 將輸入字符串編譯為字節(jié)碼。
  • 檢查字節(jié)碼對(duì)象上的.co_names,以確保它只包含允許的名字。
  • 如果用戶試圖輸入一個(gè)不允許的名字,會(huì)引發(fā)一個(gè)`NameError`。

看看下面這個(gè)函數(shù),我們?cè)谄渲袑?shí)現(xiàn)了所有這些步驟。

>>> def eval_expression(input_string):
...     # Step 1
...     allowed_names = {"sum": sum}
...     # Step 2
...     code = compile(input_string, "<string>", "eval")
...     # Step 3
...     for name in code.co_names:
...         if name not in allowed_names:
...             # Step 4
...             raise NameError(f"Use of {name} not allowed")
...     return eval(code, {"__builtins__": {}}, allowed_names)

eval_expression()? 函數(shù)可以在 eval()? 中使用的名字限制為字典 allowed_names? 中的那些名字。而該函數(shù)使用了 .co_names,它是代碼對(duì)象的一個(gè)屬性,返回一個(gè)包含代碼對(duì)象中的名字的元組。

下面的例子顯示了eval_expression() 在實(shí)踐中是如何工作的。

>>> eval_expression("3 + 4 * 5 + 25 / 2")
35.5
>>> eval_expression("sum([1, 2, 3])")
6
>>> eval_expression("len([1, 2, 3])")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in eval_expression
NameError: Use of len not allowed
>>> eval_expression("pow(10, 2)")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in eval_expression
NameError: Use of pow not allowed

如果調(diào)用 eval_expression()? 來(lái)計(jì)算算術(shù)運(yùn)算,或者使用包含允許的變量名的表達(dá)式,那么將會(huì)正常運(yùn)行并得到預(yù)期的結(jié)果,否則會(huì)拋出一個(gè)`NameError`。上面的例子中,我們僅允許輸入的唯一名字是sum()?,而不允許其他算術(shù)運(yùn)算名稱如len()和pow(),所以當(dāng)使用它們時(shí),該函數(shù)會(huì)產(chǎn)生一個(gè)`NameError`。

如果完全不允許使用名字,那么可以把 eval_expression() 改寫:

>>> def eval_expression(input_string):
...     code = compile(input_string, "<string>", "eval")
...     if code.co_names:
...         raise NameError(f"Use of names not allowed")
...     return eval(code, {"__builtins__": {}}, {})
...
>>> eval_expression("3 + 4 * 5 + 25 / 2")
35.5
>>> eval_expression("sum([1, 2, 3])")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in eval_expression
NameError: Use of names not allowed

現(xiàn)在函數(shù)不允許在輸入字符串中出現(xiàn)任何變量名。需要檢查.co_names?中的變量名,一旦發(fā)現(xiàn)就引發(fā) NameError。否則計(jì)算 input_string? 并返回計(jì)算的結(jié)果。此時(shí)也使用一個(gè)空的字典來(lái)限制locals。

我們可以使用這種技術(shù)來(lái)盡量減少eval()的安全問(wèn)題,并加強(qiáng)安全盔甲,防止惡意攻擊。

將輸入限制為只有字?jǐn)?shù)

函數(shù)eval()的一個(gè)常見用例是計(jì)算包含標(biāo)準(zhǔn)Python字面符號(hào)的字符串,并將其變成具體的對(duì)象。

標(biāo)準(zhǔn)庫(kù)提供了一個(gè)叫做 literal_eval() 的函數(shù),可以幫助實(shí)現(xiàn)這個(gè)目標(biāo)。雖然這個(gè)函數(shù)不支持運(yùn)算符,但它支持 list, tuples, numbers, strings等等。

>>> from ast import literal_eval
>>> #  計(jì)算字面意義
>>> literal_eval("15.02")
15.02
>>> literal_eval("[1, 15]")
[1, 15]
>>> literal_eval("(1, 15)")
(1, 15)
>>> literal_eval("{'one': 1, 'two': 2}")
{'one': 1, 'two': 2}
>>> # 試圖計(jì)算一個(gè)表達(dá)式
>>> literal_eval("sum([1, 15]) + 5 + 8 * 2")
Traceback (most recent call last):
  ...
ValueError: malformed node or string: <_ast.BinOp object at 0x7faedecd7668>

注意,literal_eval()?只作用于標(biāo)準(zhǔn)類型的字詞。它不支持使用運(yùn)算符或變量名。如果向 literal_eval()? 傳遞一個(gè)表達(dá)式,會(huì)得到一個(gè) ValueError。這個(gè)函數(shù)還可以將與使用eval()有關(guān)的安全風(fēng)險(xiǎn)降到最低。

使用eval()與input()函數(shù)

在 Python 3.x 中,內(nèi)置函數(shù) input() 讀取命令行上的用戶輸入,去掉尾部的換行,轉(zhuǎn)換為字符串,并將結(jié)果返回給調(diào)用者。由于 input()? 的輸出結(jié)果是一個(gè)字符串,可以把它傳遞給 eval() 并作為一個(gè) Python 表達(dá)式來(lái)計(jì)算它。

>>> eval(input("Enter a math expression: "))
Enter a math expression: 15 * 2
30
>>> eval(input("Enter a math expression: "))
Enter a math expression: 5 + 8
13

我們可以將函數(shù) eval()? 包裹在函數(shù) input()? 中,實(shí)現(xiàn)自動(dòng)計(jì)算用戶的輸入的功能。一個(gè)常見用例模擬 Python 2.x 中 input()? 的行為,input() 將用戶的輸入作為一個(gè) Python 表達(dá)式來(lái)計(jì)算,并返回結(jié)果。

因?yàn)樗婕鞍踩珕?wèn)題,因此在 Python 2.x 中的 input() 的這種行為在 Python 3.x 中被改變了。

構(gòu)建一個(gè)數(shù)學(xué)表達(dá)式計(jì)算器

到目前為止,我們已經(jīng)了解了函數(shù) eval()? 是如何工作的以及如何在實(shí)踐中使用它。此外還了解到 eval()? 具有重要的安全漏洞,盡量在代碼中避免使用 eval()?,然而在某些情況下,eval()? 可以為我們節(jié)省大量的時(shí)間和精力。因此,學(xué)會(huì)合理使用 eval() 函數(shù)還是蠻重要的。

在本節(jié)中,將編寫一個(gè)應(yīng)用程序來(lái)動(dòng)態(tài)地計(jì)算數(shù)學(xué)表達(dá)式。首先不使用eval()來(lái)解決這個(gè)問(wèn)題,那么需要通過(guò)以下步驟:

  • 解析輸入的表達(dá)式。
  • 將表達(dá)式的組成部分變?yōu)镻ython對(duì)象(數(shù)字、運(yùn)算符、函數(shù)等等)。
  • 將所有的東西合并成一個(gè)表達(dá)式。
  • 確認(rèn)該表達(dá)式在Python中是有效的。
  • 計(jì)算最終表達(dá)式并返回結(jié)果。

考慮到 Python 可以處理和計(jì)算的各種表達(dá)式非常耗時(shí)。其實(shí)我們可以使用 eval() 來(lái)解決這個(gè)問(wèn)題,而且通過(guò)上文我們已經(jīng)學(xué)會(huì)了幾種技術(shù)來(lái)規(guī)避相關(guān)的安全風(fēng)險(xiǎn)。

首先創(chuàng)建一個(gè)新的Python腳本,名為mathrepl.py,然后添加以下代碼。

import math
 
 __version__ = "1.0"
 
 ALLOWED_NAMES = {
     k: v for k, v in math.__dict__.items() if not k.startswith("__")
 }
 
 PS1 = "mr>>"

WELCOME = f"""
MathREPL {__version__}, your Python math expressions evaluator!
Enter a valid math expression after the prompt "{PS1}".
Type "help" for more information.
Type "quit" or "exit" to exit.
"""

USAGE = f"""
Usage:
Build math expressions using numeric values and operators.
Use any of the following functions and constants:
{', '.join(ALLOWED_NAMES.keys())}
"""

在這段代碼中,我們首先導(dǎo)入 math 模塊。這個(gè)模塊使用預(yù)定義的函數(shù)和常數(shù)進(jìn)行數(shù)學(xué)運(yùn)算。常量 ALLOWED_NAMES? 保存了一個(gè)包含數(shù)學(xué)中非特變量名的字典。這樣就可以用 eval() 來(lái)使用它們。

我們還定義了另外三個(gè)字符串常量。將使用它們作為腳本的用戶界面,并根據(jù)需要打印到屏幕上。

現(xiàn)在準(zhǔn)備編寫核心功能,首先編寫一個(gè)函數(shù),接收數(shù)學(xué)表達(dá)式作為輸入,并返回其結(jié)果。此外還需要寫一個(gè)叫做 evaluate() 的函數(shù),如下所示。

def evaluate(expression):
    """Evaluate a math expression."""
    # 編譯表達(dá)式
    code = compile(expression, "<string>", "eval")

    # 驗(yàn)證允許名稱
    for name in code.co_names:
        if name not in ALLOWED_NAMES:
            raise NameError(f"The use of '{name}' is not allowed")

    return eval(code, {"__builtins__": {}}, ALLOWED_NAMES)

以下是該功能的工作原理。

  • 定義了evaluate(),該函數(shù)將字符串表達(dá)式作為參數(shù),并返回一個(gè)浮點(diǎn)數(shù),代表將字符串作為數(shù)學(xué)表達(dá)式進(jìn)行計(jì)算的結(jié)果。
  • 使用compile()將輸入的字符串表達(dá)式變成編譯的Python代碼。如果用戶輸入了一個(gè)無(wú)效的表達(dá)式,編譯操作將引發(fā)一個(gè) SyntaxError。
  • 使用一個(gè)for循環(huán),檢查表達(dá)式中包含的名字,并確認(rèn)它們可以在最終表達(dá)式中使用。如果用戶提供的名字不在允許的名字列表中,那么會(huì)引發(fā)一個(gè)NameError。
  • 執(zhí)行數(shù)學(xué)表達(dá)式的實(shí)際計(jì)算。注意將自定義的字典傳遞給了globals和locals。ALLOWED_NAMES保存了數(shù)學(xué)中定義的函數(shù)和常量。

注意: 由于這個(gè)應(yīng)用程序使用了 math 中定義的函數(shù),需要注意,當(dāng)我們用一個(gè)無(wú)效的輸入值調(diào)用這些函數(shù)時(shí),其中一些函數(shù)將拋出 ValueError 異常。

例如,math.sqrt(-10)? 會(huì)引發(fā)一個(gè)異常,因?yàn)?10的平方根是未定義的。我們會(huì)在稍后的代碼中看到如何捕捉該異常。

為 globals 和 locals 參數(shù)使用自定義值,加上名稱檢查,可以將與使用eval()有關(guān)的安全風(fēng)險(xiǎn)降到最低。

當(dāng)在 main() 中編寫其代碼時(shí),數(shù)學(xué)表達(dá)式計(jì)算器就完成了。在這個(gè)函數(shù)中,定義程序的主循環(huán),結(jié)束讀取和計(jì)算用戶在命令行中輸入的表達(dá)式的循環(huán)。

在這個(gè)例子中,應(yīng)用程序?qū)ⅲ?/p>

  • 向用戶打印一條歡迎信息
  • 顯示一個(gè)提示,準(zhǔn)備讀取用戶的輸入
  • 提供獲取使用說(shuō)明和終止應(yīng)用程序的選項(xiàng)
  • 讀取用戶的數(shù)學(xué)表達(dá)式
  • 計(jì)算用戶的數(shù)學(xué)表達(dá)式
  • 將計(jì)算的結(jié)果打印到屏幕上
def main():
    """Main loop: Read and evaluate user's input."""
    print(WELCOME)
    while True:
        #  讀取用戶的輸入
        try:
            expression = input(f"{PS1} ")
        except (KeyboardInterrupt, EOFError):
            raise SystemExit()

        # 處理特殊命令
        if expression.lower() == "help":
            print(USAGE)
            continue
        if expression.lower() in {"quit", "exit"}:
            raise SystemExit()

        # 對(duì)表達(dá)式進(jìn)行計(jì)算并處理錯(cuò)誤
        try:
            result = evaluate(expression)
        except SyntaxError:
            # 如果用戶輸入了一個(gè)無(wú)效的表達(dá)式
            print("Invalid input expression syntax")
            continue
        except (NameError, ValueError) as err:
            # 如果用戶試圖使用一個(gè)不允許的名字
            # 對(duì)于一個(gè)給定的數(shù)學(xué)函數(shù)來(lái)說(shuō)是一個(gè)無(wú)效的值
            print(err)
            continue

        # 如果沒有發(fā)生錯(cuò)誤,則打印結(jié)果
        print(f"The result is: {result}")

if __name__ == "__main__":
    main()

在main()?中,首先打印WELCOME消息。然后在一個(gè)try語(yǔ)句中讀取用戶的輸入,以捕獲鍵盤中斷和 EOFError。如果這些異常發(fā)生,就終止應(yīng)用程序。

如果用戶輸入幫助選項(xiàng),那么應(yīng)用程序就會(huì)顯示使用指南。同樣地,如果用戶輸入quit或exit,那么應(yīng)用程序就會(huì)終止。

最后,使用evaluate()?來(lái)計(jì)算用戶的數(shù)學(xué)表達(dá)式,然后將結(jié)果打印到屏幕上。值得注意的是,對(duì) evaluate() 的調(diào)用會(huì)引發(fā)以下異常。

  • SyntaxError:語(yǔ)法錯(cuò)誤,當(dāng)用戶輸入一個(gè)不符合Python語(yǔ)法的表達(dá)式時(shí),就會(huì)發(fā)生這種情況。
  • NameError:當(dāng)用戶試圖使用一個(gè)不允許的名稱(函數(shù)、類或?qū)傩裕r(shí),就會(huì)發(fā)生這種情況。
  • ValueError:當(dāng)用戶試圖使用一個(gè)不允許的值作為數(shù)學(xué)中某個(gè)函數(shù)的輸入時(shí),就會(huì)發(fā)生這種情況。

注意,在main()中,捕捉了所有已知異常,并相應(yīng)地打印信息給用戶。這將使用戶能夠?qū)彶楸磉_(dá)式,修復(fù)問(wèn)題,并再次運(yùn)行程序。

現(xiàn)在已經(jīng)使用函數(shù) eval() 在大約七十行的代碼中建立了一個(gè)數(shù)學(xué)表達(dá)式計(jì)算器。要運(yùn)行這個(gè)程序,打開我們的系統(tǒng)命令行,輸入以下命令。

$ python3 mathrepl.py

這個(gè)命令將啟動(dòng)數(shù)學(xué)表達(dá)式計(jì)算器的命令行界面(CLI),會(huì)在屏幕上看到類似這樣的東西。

MathREPL 1.0, your Python math expressions evaluator!
Enter a valid math expression after the prompt "mr>>".
Type "help" for more information.
Type "quit" or "exit" to exit.

mr>>

現(xiàn)在我們可以輸入并計(jì)算任何數(shù)學(xué)表達(dá)式。例如,輸入以下表達(dá)式。

mr>> 25 * 2
The result is: 50
mr>> sqrt(25)
The result is: 5.0
mr>> pi
The result is: 3.141592653589793

如果輸入了一個(gè)有效的數(shù)學(xué)表達(dá)式,那么應(yīng)用程序就會(huì)對(duì)其進(jìn)行計(jì)算,并將結(jié)果打印到屏幕上。如果表達(dá)式有任何問(wèn)題,那么應(yīng)用程序會(huì)告訴我們。

r>> 5 * (25 + 4
Invalid input expression syntax
mr>> sum([1, 2, 3, 4, 5])
The use of 'sum' is not allowed
mr>> sqrt(-15)
math domain error
mr>> factorial(-15)
factorial() not defined for negative values

在第一個(gè)示例中,漏掉了右括號(hào),因此收到一條消息,告訴我們語(yǔ)法不正確。然后調(diào)用 sum()? ,這會(huì)得到一個(gè)解釋性的異常消息。最后,使用無(wú)效的輸入值調(diào)用“math”函數(shù),應(yīng)用程序?qū)⑸梢粭l消息來(lái)識(shí)別輸入中的問(wèn)題。

總結(jié)

你可以使用Python的 eval() 從基于字符串或基于代碼的輸入中計(jì)算Python 表達(dá)式。當(dāng)我們動(dòng)態(tài)地計(jì)算Python表達(dá)式,并希望避免從頭創(chuàng)建自己的表達(dá)式求值器的麻煩時(shí),這個(gè)內(nèi)置函數(shù)可能很有用。

在本文中,我們已經(jīng)學(xué)習(xí)了 eval() 是如何工作的,以及如何安全有效地使用它來(lái)計(jì)算任意Python表達(dá)式。

使用Python的eval()來(lái)動(dòng)態(tài)計(jì)算基本的Python表達(dá)式。

使用eval()運(yùn)行更復(fù)雜的語(yǔ)句,如函數(shù)調(diào)用、對(duì)象創(chuàng)建和屬性訪問(wèn)。

最大限度地減少與使用Python的eval()有關(guān)的安全風(fēng)險(xiǎn)。

到此這篇關(guān)于利用Python+eval函數(shù)構(gòu)建數(shù)學(xué)表達(dá)式計(jì)算器的文章就介紹到這了,更多相關(guān)Python eval數(shù)學(xué)表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python繪制的二項(xiàng)分布概率圖示例

    Python繪制的二項(xiàng)分布概率圖示例

    這篇文章主要介紹了Python繪制的二項(xiàng)分布概率圖,涉及Python基于numpy、math的數(shù)值運(yùn)算及matplotlib圖形繪制相關(guān)操作技巧,需要的朋友可以參考下
    2018-08-08
  • 對(duì)Python實(shí)現(xiàn)簡(jiǎn)單的API接口實(shí)例講解

    對(duì)Python實(shí)現(xiàn)簡(jiǎn)單的API接口實(shí)例講解

    今天小編就為大家分享一篇對(duì)Python實(shí)現(xiàn)簡(jiǎn)單的API接口實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Python中暫存上傳圖片的方法

    Python中暫存上傳圖片的方法

    這篇文章主要介紹了Python中暫存上傳圖片的方法,本文使用cStringIO模塊實(shí)現(xiàn)暫存功能,本文給出簡(jiǎn)單使用示例,需要的朋友可以參考下
    2015-02-02
  • Python實(shí)現(xiàn)獲取某天是某個(gè)月中的第幾周

    Python實(shí)現(xiàn)獲取某天是某個(gè)月中的第幾周

    這篇文章主要介紹了Python實(shí)現(xiàn)獲取某天是某個(gè)月中的第幾周,本文代碼實(shí)現(xiàn)獲取指定的某天是某個(gè)月中的第幾周、周一作為一周的開始,需要的朋友可以參考下
    2015-02-02
  • Pytorch 多塊GPU的使用詳解

    Pytorch 多塊GPU的使用詳解

    今天小編就為大家分享一篇Pytorch 多塊GPU的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python 解碼Base64 得到碼流格式文本實(shí)例

    Python 解碼Base64 得到碼流格式文本實(shí)例

    今天小編就為大家分享一篇Python 解碼Base64 得到碼流格式文本實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-01-01
  • Python3.10的一些新特性原理分析

    Python3.10的一些新特性原理分析

    由于采用了新的發(fā)行計(jì)劃:PEP 602 -- Annual Release Cycle for Python,我們可以看到更短的開發(fā)窗口,我們有望在 2021 年 10 月使用今天分享的這些新特性
    2021-09-09
  • python高級(jí)內(nèi)置函數(shù)用法實(shí)例

    python高級(jí)內(nèi)置函數(shù)用法實(shí)例

    在本篇文章里小編給大家整理的是一篇關(guān)于python高級(jí)內(nèi)置函數(shù)用法實(shí)例內(nèi)容,有興趣的朋友們可以學(xué)參考下。
    2021-09-09
  • pygame實(shí)現(xiàn)打字游戲

    pygame實(shí)現(xiàn)打字游戲

    這篇文章主要為大家詳細(xì)介紹了pygame實(shí)現(xiàn)打字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Python 同級(jí)目錄(兄弟目錄)調(diào)用方式

    Python 同級(jí)目錄(兄弟目錄)調(diào)用方式

    這篇文章主要介紹了Python 同級(jí)目錄(兄弟目錄)調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評(píng)論