Python eval ()

Metoda eval () analizuje wyrażenie przekazane do tej metody i uruchamia wyrażenie (kod) języka Python w programie.

Mówiąc prościej, eval()funkcja uruchamia kod Pythona (który jest przekazywany jako argument) w programie.

Składnia eval()to:

 eval (wyrażenie, globals = None, locals = None)

eval () Parametry

eval()Funkcja przyjmuje trzy parametry:

  • wyrażenie - ciąg przeanalizowany i oceniony jako wyrażenie Pythona
  • globals (opcjonalnie) - słownik
  • locals (opcjonalnie) - obiekt mapujący. Słownik to standardowy i powszechnie używany typ mapowania w Pythonie.

Użycie zmiennych globalnych i lokalnych zostanie omówione w dalszej części tego artykułu.

Wartość zwracana z eval ()

Metoda eval () zwraca wynik obliczony na podstawie wyrażenia.

Przykład 1: Jak eval () działa w Pythonie

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

Wynik

 2

W tym przypadku eval()funkcja ocenia wyrażenie x + 1i printjest używana do wyświetlenia tej wartości.

Przykład 2: Praktyczny przykład do zademonstrowania użycia 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

Wynik

 Wpisz funkcję: oblicz obszar (l) Jeśli długość wynosi 1, Powierzchnia = 1 Jeśli długość wynosi 2, Powierzchnia = 4 Jeśli długość wynosi 3, Powierzchnia = 9 Jeśli długość wynosi 4, Powierzchnia = 16

Ostrzeżenia podczas używania eval ()

Rozważ sytuację, w której używasz systemu Unix (macOS, Linux itp.) I zaimportowałeś osmoduł. Moduł os zapewnia przenośny sposób korzystania z funkcji systemu operacyjnego, takich jak odczyt lub zapis do pliku.

Jeśli pozwalają użytkownikom na wejście wartość za pomocą eval(input()), użytkownik może wydać polecenia do pliku wymiany lub nawet usunąć wszystkie pliki za pomocą polecenia: os.system('rm -rf *').

Jeśli używasz eval(input())w swoim kodzie, dobrym pomysłem jest sprawdzenie, jakich zmiennych i metod może użyć użytkownik. Możesz zobaczyć, które zmienne i metody są dostępne za pomocą metody dir ().

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

Wynik

('__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', ' asinh ”,„ atan ”,„ atan2 ”,„ atanh ”,„ ceil ”,„ comb ”,„ copysign ”,„ cos ”,„ cosh ”,„ steps ”,„ dist ”,„ e ”,„ erf ” , „erfc”, „exp”, „expm1”, „fabs”, „silnia”, „podłoga”, „fmod”, „frexp”, „fsum”, „gamma”, „gcd”, „hypot”, „ inf ”,„ isclose ”,„ isfinite ”,„ isinf ”,„ isnan ”,„ isqrt ”,„ ldexp ”,„ lgamma ”,„ log ”,„ log10 ”,„ log1p ”,„log2 ”,„ modf ”,„ nan ”,„ os ”,„ perm ”,„ pi ”,„ pow ”,„ prod ”,„ radians ”,„ others ”,„ sin ”,„ sinh ”,„ sqrt ” , „tan”, „tanh”, „tau”, „obcięcie”)

Ograniczenie użycia dostępnych metod i zmiennych w eval ()

Najczęściej wszystkie dostępne metody i zmienne użyte w wyrażeniu (pierwszy parametr do eval()) mogą nie być potrzebne, a nawet mogą mieć lukę w zabezpieczeniach. Może być konieczne ograniczenie korzystania z tych metod i zmiennych dla eval(). Możesz to zrobić, przekazując do funkcji opcjonalne parametry globalne i lokalne (słowniki) eval().

1. Gdy pominięto zarówno parametry globalne, jak i lokalne

Jeśli oba parametry zostaną pominięte (jak we wcześniejszych przykładach), wyrażenie jest wykonywane w bieżącym zakresie. Możesz sprawdzić dostępne zmienne i metody za pomocą następującego kodu:

 print(eval('dir()')

2. Przekazywanie parametru globals; parametr locals jest pominięty

Parametry globalne i lokalne (słowniki) są używane odpowiednio dla zmiennych globalnych i lokalnych. Jeśli pominięto słownik lokalny, domyślnie jest to słownik globalny. Oznacza to, że wartości globalne będą używane zarówno dla zmiennych globalnych, jak i lokalnych.

Uwaga: Możesz sprawdzić bieżący słownik globalny i lokalny w Pythonie, używając odpowiednio wbudowanych metod globals () i locals ().

Przykład 3: przekazanie pustego słownika jako parametru globalnego

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

Wynik

 ('__builtins__') Traceback (ostatnie wywołanie ostatnie): Plik "", wiersz 5, in print (eval ('sqrt (25)', ())) Plik "", wiersz 1, w NameError: name 'sqrt' nie jest zdefiniowany

Jeśli przekażesz pusty słownik jako globals, tylko __builtins__są dostępne dla expression(pierwszy parametr do eval()).

Mimo że zaimportowaliśmy mathmoduł do powyższego programu, wyrażenie nie może uzyskać dostępu do żadnych funkcji udostępnianych przez moduł matematyczny.

Przykład 4: Udostępnianie określonych metod

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

Wynik

 („__builtins__”, „pow”, „sqrt”)

Tutaj wyrażenie można użyć tylko sqrt()i tych pow()metod wraz z __builtins__.

Możliwa jest również zmiana nazwy metody dostępnej dla wyrażenia według własnego uznania:

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

Wynik

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

W powyższym programie square_root()oblicza pierwiastek kwadratowy za pomocą sqrt(). Jednak próba sqrt()bezpośredniego użycia spowoduje błąd.

Przykład 5: Ograniczenie używania wbudowanych

Możesz ograniczyć użycie __builtins__wyrażenia w następujący sposób:

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

3. Przekazanie zarówno globalnego, jak i lokalnego słownika

Możesz udostępnić potrzebne funkcje i zmienne do użytku, przekazując słownik lokalnych. Na przykład:

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

Wynik

 13,0

W tym programie wyrażenie może mieć tylko sqrt()metodę i zmienną a. Wszystkie inne metody i zmienne są niedostępne.

Ograniczenie używania eval()przez przekazywanie globalnych i lokalnych słowników sprawi, że kod będzie bezpieczny, szczególnie w przypadku korzystania z danych wejściowych dostarczonych przez użytkownika do eval()metody.

Uwaga: czasami eval()nie jest bezpieczny nawet w przypadku ograniczonych nazw. Gdy obiekt i jego metody stają się dostępne, można zrobić prawie wszystko. Jedynym bezpiecznym sposobem jest sprawdzenie poprawności danych wejściowych użytkownika.

Interesujące artykuły...