Python eval ()

Phương thức eval () phân tích cú pháp biểu thức được truyền cho phương thức này và chạy biểu thức python (mã) trong chương trình.

Nói một cách dễ hiểu, eval()hàm chạy mã python (được truyền dưới dạng đối số) trong chương trình.

Cú pháp của eval()là:

 eval (biểu thức, hình cầu = Không có, địa phương = Không có)

eval () Tham số

Các eval()chức năng có ba thông số:

  • biểu thức - chuỗi được phân tích cú pháp và đánh giá như một biểu thức Python
  • toàn cầu (tùy chọn) - từ điển
  • địa phương (tùy chọn) - một đối tượng ánh xạ. Từ điển là loại ánh xạ tiêu chuẩn và thường được sử dụng trong Python.

Việc sử dụng hình cầu và địa phương sẽ được thảo luận sau trong bài viết này.

Giá trị trả về từ eval ()

Phương thức eval () trả về kết quả được đánh giá từ biểu thức.

Ví dụ 1: Cách eval () hoạt động trong Python

 x = 1 print(eval('x + 1'))

Đầu ra

 2

Ở đây, eval()hàm đánh giá biểu thức x + 1printđược sử dụng để hiển thị giá trị này.

Ví dụ 2: Ví dụ thực tế để chứng minh việc sử dụng eval ()

 # Perimeter of Square def calculatePerimeter(l): return 4*l # Area of Square def calculateArea(l): return l*l expression = input("Type a function: ") for l in range(1, 5): if (expression == 'calculatePerimeter(l)'): print("If length is ", l, ", Perimeter = ", eval(expression)) elif (expression == 'calculateArea(l)'): print("If length is ", l, ", Area = ", eval(expression)) else: print('Wrong Function') break

Đầu ra

 Nhập hàm: Tính toánArea (l) Nếu độ dài là 1, Diện tích = 1 Nếu độ dài là 2, Diện tích = 4 Nếu độ dài là 3, Diện tích = 9 Nếu độ dài là 4, Diện tích = 16

Cảnh báo khi sử dụng eval ()

Xem xét tình huống bạn đang sử dụng hệ thống Unix (macOS, Linux, v.v.) và bạn đã nhập osmô-đun. Mô-đun hệ điều hành cung cấp một cách di động để sử dụng các chức năng của hệ điều hành như đọc hoặc ghi vào tệp.

Nếu bạn cho phép người dùng nhập vào một giá trị sử dụng eval(input()), người dùng có thể ra lệnh cho tập tin thay đổi hoặc thậm chí xóa tất cả các file bằng cách sử dụng lệnh: os.system('rm -rf *').

Nếu bạn đang sử dụng eval(input())mã của mình, bạn nên kiểm tra các biến và phương pháp mà người dùng có thể sử dụng. Bạn có thể xem các biến và phương thức nào có sẵn bằng cách sử dụng phương thức dir ().

 from math import * print(eval('dir()'))

Đầu ra

('__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', ' asinh ',' atan ',' atan2 ',' atanh ',' ceil ',' comb ',' copysign ',' cos ',' cosh ',' Degree ',' dist ',' e ',' erf ' , 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'pseud', ' inf ',' isclose ',' isfinite ',' isinf ',' isnan ',' isqrt ',' ldexp ',' lgamma ',' log ',' log10 ',' log1p ','log2 ',' modf ',' nan ',' os ',' perm ',' pi ',' pow ',' prod ',' radians ',' remainder ',' sin ',' sinh ',' sqrt ' , 'tan', 'tanh', 'tau', 'trunc')

Hạn chế việc sử dụng các phương thức và biến có sẵn trong eval ()

Thường xuyên hơn không, tất cả các phương thức và biến có sẵn được sử dụng trong biểu thức (tham số đầu tiên đến eval()) có thể không cần thiết, hoặc thậm chí có thể có lỗ hổng bảo mật. Bạn có thể cần phải hạn chế việc sử dụng các phương pháp và biến này cho eval(). Bạn có thể làm như vậy bằng cách chuyển các tham số hình cầu và cục bộ tùy chọn (từ điển) vào eval()hàm.

1. Khi cả tham số hình cầu và địa phương bị bỏ qua

Nếu cả hai tham số bị bỏ qua (như trong các ví dụ trước đó của chúng tôi), biểu thức sẽ được thực thi trong phạm vi hiện tại. Bạn có thể kiểm tra các biến và phương pháp có sẵn bằng cách sử dụng mã sau:

 print(eval('dir()')

2. Truyền tham số global; tham số địa phương bị bỏ qua

Các tham số toàn cầu và địa phương (từ điển) được sử dụng cho các biến toàn cục và cục bộ tương ứng. Nếu từ điển địa phương bị bỏ qua, nó sẽ mặc định là từ điển toàn cầu. Có nghĩa là, toàn cầu sẽ được sử dụng cho cả biến toàn cục và biến cục bộ.

Lưu ý: Bạn có thể kiểm tra từ điển cục bộ và toàn cục hiện tại bằng Python bằng cách sử dụng các phương thức tích hợp sẵn tương ứng với các phương thức tích hợp global () và local ().

Ví dụ 3: Truyền từ điển trống dưới dạng tham số toàn cầu

 from math import * print(eval('dir()', ())) # The code will raise an exception print(eval('sqrt(25)', ()))

Đầu ra

 ('__builtins__') Traceback (lần gọi gần đây nhất): Tệp "", dòng 5, in (eval ('sqrt (25)', ())) Tệp "", dòng 1, trong NameError: name 'sqrt' không được xác định

Nếu bạn chuyển một từ điển trống dưới dạng toàn cầu, chỉ __builtins__có sẵn cho expression(tham số đầu tiên cho eval()).

Mặc dù chúng tôi đã nhập mathmô-đun trong chương trình trên, biểu thức không thể truy cập bất kỳ hàm nào được cung cấp bởi mô-đun toán học.

Ví dụ 4: Làm cho một số phương pháp có sẵn

 from math import * print(eval('dir()', ('sqrt': sqrt, 'pow': pow)))

Đầu ra

 ('__builtins__', 'pow', 'sqrt')

Ở đây, biểu thức chỉ có thể sử dụng các sqrt()và các pow()phương thức cùng với __builtins__.

Cũng có thể thay đổi tên của phương thức có sẵn cho biểu thức theo ý muốn của bạn:

 from math import * names = ('square_root': sqrt, 'power': pow) print(eval('dir()', names)) # Using square_root in Expression print(eval('square_root(9)', names))

Đầu ra

 ('__builtins__', 'power', 'square_root') 3.0

Trong chương trình trên, square_root()sử dụng tính toán căn bậc hai sqrt(). Tuy nhiên, cố gắng sử dụng sqrt()trực tiếp sẽ phát sinh lỗi.

Ví dụ 5: Hạn chế việc sử dụng cài sẵn

Bạn có thể hạn chế việc sử dụng __builtins__trong biểu thức như sau:

 eval(expression, ('__builtins__': None))

3. Vượt qua cả từ điển toàn cầu và địa phương

Bạn có thể cung cấp các hàm và biến cần thiết để sử dụng bằng cách chuyển từ điển địa phương. Ví dụ:

 from math import * a = 169 print(eval('sqrt(a)', ('__builtins__': None), ('a': a, 'sqrt': sqrt)))

Đầu ra

 13.0

Trong chương trình này, biểu thức chỉ có thể có sqrt()phương thức và biến a. Tất cả các phương pháp và biến khác không có sẵn.

Hạn chế sử dụng eval()bằng cách chuyển các từ điển toàn cầu và địa phương sẽ làm cho mã của bạn an toàn, đặc biệt khi bạn đang sử dụng đầu vào do người dùng cung cấp cho eval()phương thức.

Lưu ý: Đôi khi, eval()không an toàn ngay cả với các tên hạn chế. Khi một đối tượng và các phương thức của nó được làm cho có thể truy cập được, hầu hết mọi thứ đều có thể được thực hiện. Cách an toàn duy nhất là xác thực đầu vào của người dùng.

thú vị bài viết...