Zanurkuj w Pythonie/Odwzorowywanie listy

Odwzorowywanie list

edytuj

Jedną z bardzo użytecznych cech Pythona są wyrażenia listowe (ang. list comprehension), które pozwalają nam w zwięzły sposób odwzorować pewną listę na inną, wykonując na każdym jej elemencie pewną funkcję.

Przykład. Wprowadzenie do wyrażeń listowych
>>> li = [1, 9, 8, 4]
>>> [element*2 for element in li]      #(1)
[2, 18, 16, 8]
>>> li                                 #(2)
[1, 9, 8, 4]
>>> li = [elem*2 for elem in li]       #(3)
>>> li
[2, 18, 16, 8]

  1. Aby zrozumieć o co w tym chodzi, spójrzmy na to od strony prawej do lewej. li jest listą, którą odwzorowujemy. Python przechodzi po każdym elemencie li, tymczasowo przypisując wartość każdego elementu do zmiennej element, a następnie wyznacza wartość funkcji element*2 i wstawia wynik do nowej, zwracanej listy.
  2. Wyrażenia listowe nie zmieniają oryginalnej listy.
  3. Zwracany wynik możemy przypisać do zmiennej, którą odwzorowujemy. Nie spowoduje to żadnych problemów. Python tworzy nową listę w pamięci, a kiedy operacja odwzorowywania listy dobiegnie końca, do zmiennej zostanie przypisana lista znajdująca się w pamięci.

W funkcji buildConnectionString zadeklarowanej w rozdziale 2 skorzystaliśmy z wyrażeń listowych:

["%s=%s" % (k, v) for k, v in params.items()]

Zauważmy, że najpierw wykonujemy funkcję items, znajdującą się w słowniku params. Funkcja ta zwraca wszystkie dane znajdujące się w słowniku w postaci listy krotek.

Przykład. Funkcje keys, values i items
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()                        #(1)
['pwd', 'database', 'uid', 'server']
>>> params.values()                      #(2)
['secret', 'master', 'sa', 'mpilgrim']
>>> params.items()                       #(3)
[('pwd', 'secret'), ('database', 'master'), ('uid', 'sa'), ('server', 'mpilgrim')]

  1. W słowniku metoda keys zwraca listę wszystkich kluczy. Lista ta nie jest uporządkowana zgodnie z kolejnością, z jaką definiowaliśmy słownik (pamiętamy, że elementy w słowniku są nieuporządkowane).
  2. Metoda values zwraca listę wszystkich wartości. Lista ta jest zgodna z porządkiem listy zwracanej przez metodę keys, czyli dla wszystkich wartości x zachodzi params.values()[x] == params[params.keys()[x]].
  3. Metoda items zwraca listę krotek w formie (klucz, wartość). Lista zawiera wszystkie dane ze słownika.

Spójrzmy jeszcze raz na funkcję buildConnectionString. Przyjmuje ona listę params.items(), odwzorowuje ją na nową listę, korzystając dla każdego elementu z formatowania łańcucha znaków. Nowa lista ma tyle samo elementów co params.items(), lecz każdy element nowej listy jest łańcuchem znaków, który zawiera zarówno klucz, jak i skojarzoną z nim wartość ze słownika params.

Przykład. Wyrażenia listowe w buildConnectionString
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.items()
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
>>> [k for k, v in params.items()]                                                      #(1)
['server', 'uid', 'database', 'pwd']
>>> [v for k, v in params.items()]                                                      #(2)
['mpilgrim', 'sa', 'master', 'secret']
>>> ["%s=%s" % (k, v) for k, v in params.items()]                                       #(3)
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']

  1. Wykonując iteracje po liście params.items() używamy dwóch zmiennych. Zauważmy, że w ten sposób korzystamy w pętli z wielozmiennego przypisania. Pierwszym elementem params.items() jest ('server', 'mpilgrim'), dlatego też podczas pierwszej iteracji odwzorowywania listy zmienna k będzie przechowywała wartość 'server', a v wartość 'mpilgrim'. W tym przypadku ignorujemy wartość v, dołączając tylko wartość znajdującą się w k do zwracanej listy. Otrzymamy taki sam wynik, gdy wywołamy params.keys().
  2. W tym miejscu wykonujemy to samo, ale zamiast zmiennej v ignorujemy zmienną k. Otrzymamy taki sam wynik, jakbyśmy wywołali params.values().
  3. Dzięki temu, że przerobiliśmy obydwa poprzednie przykłady i skorzystaliśmy z formatowania łańcucha znaków, otrzymaliśmy listę łańcuchów znaków. Każdy łańcuch znaków tej listy zawiera zarówno klucz, jak i wartość pewnego elementu ze słownika. Wynik wygląda podobnie do wyjścia pierwszego programu. Ponadto porządek został taki sam, jaki był w słowniku.

Materiały dodatkowe

edytuj