Better python for network engineers
: 08 mar 2017, 14:00
Czesc tak sobie pomyslalem ze podziele sie jak functional programming moze ulatwic prace ze strukturami danych
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
Zadanie nr 1.
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.
Ble.. ile kodu!! na prosta operacje, zobaczmy jak poradzi sobie list comprehension
b) List comprehension
Znacznie lepiej prawda No ale to jeszcze nie jest to co bysmy chcieli. Zobaczmy jak mozna to zrobic metoda filter
c) Metoda filter
Dobra zgodze sie metoda filter jest znacznie bardziej magiczna, ale to tylko pierwsze wrazenie. Na pewno lambda moze spowodowac ze niektorzy zwatpia
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.
Sweet, jedna linia kodu a jaka operacja
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
Bam ! jedna linia kodu !! Mam nadzieje ze zacheci to was do chociaz przemyslenia programowania funkcyjnego jako metody pracy ze strukturami. Przy dluzszym obcowaniu
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
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