tags: Python Tips
寫在前面
今天刷幾道關于數的運算的題, 我發現了一個很匪夷所思的問題:
兩段幾乎完全一樣的代碼, 其運作時間差異怎麼會如此之大呢?(題目:415. 字元串相加 - 力扣(LeetCode))
# 我的代碼
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
na,nb=len(num1)-1,len(num2)-1
add=0
ans=''
while na>=0 or nb>=0 or add:
a=eval(num1[na]) if na>=0 else 0
b=eval(num2[nb]) if nb>=0 else 0
tmp=a+b+add
ans+=str(tmp%10)
add=tmp//10
na-=1
nb-=1
return ans[::-1]
下面是官方代碼:
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
na,nb=len(num1)-1,len(num2)-1
add=0
ans=''
while na>=0 or nb>=0:
a=int(num1[na]) if na>=0 else 0
b=int(num2[nb]) if nb>=0 else 0
tmp=a+b+add
ans=str(tmp%10)+ans
add=tmp//10
na-=1
nb-=1
return '1'+ans if add else ans
乍一看沒什麼問題, 但是我的代碼就是
188ms
, 而官方的是
36ms
, 這就很奇怪了…
分析
後來一番對比發現, 真正的罪魁禍首并不在代碼邏輯方面, 而在于一個小小的API函數
eval()
, 這個函數雖然也能将字元串轉換為整數, 但是其效率非常低…
其實從力扣的判題就能看出來了, 但是我還是想在本地試試:
from time import time
st=time()
ans=[]
for i in range(10000000):
ans.append(eval(str(i)))
print("ok")
print("time :", time()-st)
上面的代碼運作時間為:
34.3s
, 而将
eval
換成
int
之後程式運作時間隻有
3.6s
, 足可見其對運作效率的影響.
那麼, 到底是什麼原因導緻差異的呢?
eval()與int()比較
這裡參考了一些stack的回答1.
-
函數隻能對僅含有整數的字元串做處理, 而并不進行字元串的檢查, 當然, 這裡一個額外的情況如下:int()
In [1]: int('01')
Out[1]: 1
In [2]: eval('01')
File <string>:1
01
^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers
可以看到前導零并不會影響
int
, 但是
eval
會首先将前導零認為是八進制數字, 這也是
int()
和
eval()
在整數轉換時候不一樣的地方(int更勝一籌);
- 對于浮點數, 隻能使用
, 看下面的例子:eval()
In [3]: int('1.1')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [3], in <cell line: 1>()
----> 1 int('1.1')
ValueError: invalid literal for int() with base 10: '1.1'
In [4]: eval('1.1')
Out[4]: 1.1
- 在與
搭配使用eval()
的時候需要注意, 由于input()
eval()
會執行Python中的表達式, 那就會有下面的一個問題.
一般的Python入門書中對于使用者輸入都是這樣寫的:
x=eval(input("Enter a number:"))
x=eval(input("Enter a number:"))
# 此時輸入下面的内容
__import__('os').system("rm -rf *")
ref
- python - “eval”和“int”有什麼差別 - Stack Overflow; ↩︎