Dynamiczne wywołanie funkcji

Język Python ma sporo ukrytych ciekawych funkcjonalności. Wiele z nich odpowiednio wykorzystane mogą uprościć kod naszej aplikacji, eliminując skomplikowane konstrukcje warunków. Jedną z moich ulubionych jest możliwość wywoływania metod poprzez dynamiczne tworzenie ich nazwy w wywołaniu z zastosowaniem zmiennych. Ta technika nie ma swojej unikalnej nazwy. Dla mnie jest to najczęściej dynamiczne wywołanie funkcji.

Zacznijmy od banalnego przykładu

Przyjrzyjmy się takiej prozaicznej sytuacji – w zależności od wartości wskazanej zmiennej, chcemy wykonać jedną z napisanych przez nas metod. Pierwsza myśl, jaka powinna Ci już przyjść do głowy, to zastosowanie konstrukcji warunkowych if. W ten sposób zbadamy wartość wskazanej zmiennej i uzależnimy od tego wywołanie odpowiedniej metody. Przyjrzyjmy się zatem takiemu rozwiązaniu:

def method_A(x, y):
    print(x+y)

def method_B(x, y):
    print(x+y+1)

def method_C(x, y):
    print(x+y+2)

i = 'B'

if i is 'A':
    method_A(1, 2)
elif i is 'B':
    method_B(1, 2)
elif i is 'C':
    method_C(1, 2)

W powyższym przykładzie stworzyłem trzy metody, a następnie za pomocą konstrukcji warunkowych if-elif badam wartość zmiennej i, aby w zależności od jej wartości uruchomić odpowiednią metodę.

Ten przykład jest oczywiście bardzo prosty. W rozbudowanych aplikacjach metod do wywołania może być wiele, co prowadziłoby do tworzenia dużych konstrukcji warunkowych. Czasami mogą one być powiązane też z pętlami. Czy da się zaimplementować to w nieco bardziej elastyczny sposób?

Zmienna w nazwie wywoływanej metody?

Gdy tworzymy nową funkcję, to musimy jej nadać jednoznaczną nazwę. Wywołując ją, możemy jednak nie podawać jej nazwy wprost. Zamiast tego możemy stworzyć dynamiczne wywołanie funkcji konstruując wywoływaną nazwę metody z użyciem zmiennych. Spójrz, że już w samej konstrukcji warunkowej z pierwszego przykładu to jednoznaczna wartość zmiennej i determinowała, która z metod zostanie uruchomiona. Zatem powyższą konstrukcję if-elif możemy uprościć do następującego zapisu:

globals()['method_' + i](1, 2)

Za pomocą wbudowanej systemowej metody globals() odczytamy informację o zaalokowanych na potrzeby działania naszego programu obiektach. Zwracana przez nią wartość jest obiektem typu dictionary i nazywany jest Global Symbol Table. Znajdziemy w nim między innymi wpis {'i': 'C'}, czyli rekord, którego kluczem jest nazwa zdefiniowanej przez nas zmiennej a wartością aktualny jej stan na moment wywołania funkcji globals(). Jako klucze w słowniku odnajdziemy też zdefiniowane przez nas metody, a wartością do nich przypisaną będą odniesienia do odpowiednich obszarów pamięci, na przykład ‘{ method_A’: .

Ponieważ funkcja globals() zwraca słownik, to nic nie stoi na przeszkodzie, abyśmy, zamiast wywoływać funkcję bezpośrednio, uruchomili ją poprzez wywołanie obiektu z tego słownika, gdzie kluczem będzie nazwa wywoływanej metody. Idąc tym tropem krok dalej, nic nie stoi na przeszkodzie, abyśmy nazwę tego klucza składali “w locie”. Dokładnie to się dzieje w nawiasach kwadratowych, gdzie do stałego ciągu “method_” dołączamy aktualną wartość zmiennej i tworząc tym samym pełną nazwę klucza.

Jeżeli chcesz korzystać z zaprezentowanej przeze mnie techniki pamiętaj, aby odpowiednio zaplanować nazewnictwo swoich funkcji.


Subscribe
Powiadom o
guest

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

0 komentarzy
Inline Feedbacks
View all comments

ZdradziĆ Ci sekretY udanego projektu automatyzacji?

(link otwiera się w nowym oknie)