Na poczatku jedno zdanie czym jest functional programming. To podejscie do programowania i pisania kodu ktory w zasadzie
nie powinien modyfikowac danych wejsciowych (pure functions), byc odporny na bugi, zapobiegac DRY(Don't repeat yourself)
i byc jak najkrotszy.
Kilka przykladow:
zakladamy ze mamy prosta strukture danych jak ponizej, gdzie interfaces to tablica/lista zawierajaca slowniki
gdzie kazdy slownik odpowiada wartoscia(danym) z danego interfejsu
Kod: Zaznacz cały
interfaces = [{"type":"GitabitEthernet", "status":"up", "rx":2000, "tx":3000, "id":1},
{"type":"GigabitEthernet", "status":"up", "rx":2100, "tx":3309, "id":2},
{"type":"GigabitEthernet", "status":"down", "rx":200, "tx":5000, "id":3},
{"type":"GigabitEthernet", "status":"up", "rx":1000, "tx":2000, "id":4}]
Zwrocic interfejsy ktore sa w stanie up.
Mozna to zrobic na dwa trzy sposoby.
a) Tradycyjny: petla for sprawdzenie warunku i wrzuceniu do nowej listy
interfejsy spelniajace warunek.
Kod: Zaznacz cały
>>> def traditionalFunc(status,interfaces):
... statusInterfaces = []
... for x in interfaces:
... if x.get('status') == status:
... statusInterfaces.append(x)
... return statusInterfaces
...
>>> traditionalFunc('up')
[{'type': 'GitabitEthernet', 'id': 1, 'status': 'up', 'tx': 3000, 'rx': 2000}, {'type': 'GigabitEthernet', 'id': 2, 'status': 'up', 'tx': 3309, 'rx': 2100}, {'type': 'GigabitEthernet', 'id': 4, 'status': 'up', 'tx': 2000, 'rx': 1000}]
b) List comprehension
Kod: Zaznacz cały
>>> def comprehensionFunc(status,interfaces):
... return [x for x in interfaces if x.get('status') == status]
...
>>>
>>> comprehensionFunc('up',interfaces)
[{'type': 'GitabitEthernet', 'id': 1, 'status': 'up', 'tx': 3000, 'rx': 2000}, {'type': 'GigabitEthernet', 'id': 2, 'status': 'up', 'tx': 3309, 'rx': 2100}, {'type': 'GigabitEthernet', 'id': 4, 'status': 'up', 'tx': 2000, 'rx': 1000}]
>>>
c) Metoda filter
Kod: Zaznacz cały
>>> interfacesStatus = list(filter(lambda x: x.get('status')=='up', interfaces))
>>>
>>> interfacesStatus
[{'type': 'GitabitEthernet', 'id': 1, 'status': 'up', 'tx': 3000, 'rx': 2000}, {'type': 'GigabitEthernet', 'id': 2, 'status': 'up', 'tx': 3309, 'rx': 2100}, {'type': 'GigabitEthernet', 'id': 4, 'status': 'up', 'tx': 2000, 'rx': 1000}]
w funkcyjne programowanie ale nie taki diabel straszny jak go maluja !. Lambda to nic innego jak nie nazwana funkcja ktora moze przyjac dowolna ilosc argumentow (wszystko przed a nastepnie poslugujac sie tymi argumentami wykonac okreslona operacje na strukturze ktora jest drugim argumentem do funkcji filter. Sam filter zwraca nam obiekt wiec musimy zamienic to na strukturke metoda list ktora zwroci nam liste.
Kolejny przyklad mam nadzieje pokaze wiecej prawdziwej mocy drzemiacej w programowaniu funkcyjnym.
Zadanie 2.
Zwrocic sume wszystkich RX Jako zadanko mozna sprobwoac metody tradycyjnej i list comprehension, ja natomiast chce pokazac jak zrobic to za pomoca pure funkcji
o nazwie map + sum.
Kod: Zaznacz cały
>>> rxSum = sum(list(map(lambda x: x.get('rx'), interfaces)))
>>> rxSum
5300
Teraz.. nikt nei zabroni nam laczyc metod do bardziej wymyslonych warunkow. Zrobmy teraz tak, dodajmy tylko TX interfejsow ktore sa w stanie UP, nie inetresuja nas interfejsy ktore sa down tym razem
Kod: Zaznacz cały
>>> txSum = sum(list(map(lambda x: x.get('status') == 'up' and x.get('tx'), interfaces)))
>>>
>>> txSum
8309
i wprawie obiecuje wam ze nie bedziecie chcieli juz pisac tradycyjnych petli.
Jak ktos dokladnie chce wiedziec jak dziala list comprehension to zapraszam do mnie na bloga http://horac.pl
Pozdr