Zanurkuj w Pythonie/plural.py, etap 3

Zauważmy, że definiowanie osobnych, nazwanych funkcji dla każdej reguły dopasowującej i modyfikującej nie jest tak naprawdę konieczne. Nigdy nie wywołujemy tych funkcji bezpośrednio; definiujemy je w krotce rules i wywołujemy je również przy użyciu tej krotki. Spróbujmy zatem przekształcić je do funkcji anonimowych.

Przykład 17.8. plural3.py

import re

rules = \
  (
    (
     lambda word: re.search('[sxz]$', word),
     lambda word: re.sub('$', 'es', word)
    ),
    (
     lambda word: re.search('[^aeioudgkprt]h$', word),
     lambda word: re.sub('$', 'es', word)
    ),
    (
     lambda word: re.search('[^aeiou]y$', word),
     lambda word: re.sub('y$', 'ies', word)
    ),
    (
     lambda word: re.search('$', word),
     lambda word: re.sub('$', 's', word)
    )
   )                                           #(1)

def plural(noun):                             
    for matchesRule, applyRule in rules:       #(2)
        if matchesRule(noun):                 
            return applyRule(noun)
  1. To ten sam zestaw reguł, który widzieliśmy na etapie 2. Jedyna różnica polega na tym, że zamiast definiować funkcje nazwane, takie jak match_sxz czy apply_sxz, włączyliśmy treść tych funkcji bezpośrednio do zmiennej rules używając funkcji lambda.
  2. Zauważmy, że funkcja plural w ogóle sie nie zmieniła. Iteruje ona po zestawie funkcji reprezentujących reguły, sprawdza pierwszą regułę, a jeśli zwróci ona wartość true, wywołuje ona drugą regułę i zwraca jej wynik. Dokładnie tak samo, jak wcześniej. Jedyna różnica polega teraz na tym, że funkcje z regułami zostały zdefiniowane "inline", jako funkcje anonimowe, przy użyciu funkcji lambda. Jednak dla funkcji plural sposób zdefiniowania funkcji nie ma żadnego znaczenia; otrzymuje ona listę reguł i wykonuje na niej swoją pracę.

Aby dodać nową regułę tworzenia liczby mnogiej, wystarczy zdefiniować nowe funkcje (regułę dopasowującą oraz regułę modyfikującą) bezpośrednio w samej krotce rules. Teraz jednak, kiedy mamy zdefiniować reguły wewnątrz krotki, widzimy wyraźnie, że pojawiły się liczne niepotrzebne powtórzenia kodu. Mamy bowiem cztery pary funkcji, a każda z nich jest napisana według tego samego wzorca. Funkcje dopasowujące składają się z pojedynczego wywołania re.search, a funkcje modyfikujące - z wywołania re.sub. Spróbujmy zrefaktoryzować te podobieństwa.