(Niezbyt) oczywiste elementy Pythona¶
Niniejszy kurs zakłada podstawową znajomość języka Python. Czytelnik nie znajdzie tu opisu jak tworzyć pętle czy instrukcje warunkowe. Aby uzupełnić wiedzę w tym zakresie polecam lekturę moich notatek do Podstaw programowania w języku Python Na początku jednak przypomnę pewne mniej oczywiste elementy tego języka, które będą bardzo przydatne przy omawianiu programowania obiektowego.
args i kwargs¶
Jednym z ważnych mechanizmów programowania obiektowego jest przeciążenie funkcji. Zaczniemy to wykorzystywać już niedługo. Jedynym sposobem implementacji tego mechanizmu w Pythonie jest wykorzystanie args i kwargs. Opisano je na tej stronie
Zmienne istnieją od momentu pierwszego przypisania¶
To w zasadzie powinno być oczywiste, stanowi podstawę programowania w języku Python. Dla przypomnienia jednak powtórzmy: w odróżnieniu od języków kompilowanych takich jak Java czy C++, w Pythonie nie deklarujemy zmiennych. Zmienne tworzymy przez nadawanie wartości.
Zmienne globalne i lokalne¶
Zmienne mogą być lokalne lub globalne. Róznice między nimi opisano na tej stronie
Wszystko jest tym czym jest …¶
… no chyba, że jest referencją tego czegoś
Przeanalizuj poniższy przykład, który w zasadzie powinien stworzyć macierz 3x3 z elementami 1, 2 i 3:
Co ten program wydrukuje na ekranie? Dlaczego? Co się zmieni po odkomentowaniu linii nr 4?
Referencje bywają jednak bardzo przydatne. Dzięki temu zachowanie danego obiektu może zależeć od stanu innego obiektu. W poniższym przykładzie obiekt klasy LJ, obliczającego energię Lennard-Jonesa, śledzi położenia przemieszczających się atomów.
Dzięki temu nie trzeba przekazywać ich jako argumentów funkcji przy każdym wywołaniu.
Funkcja tak jak zmienna¶
Funkcję w języku Python można przekazać jako argument, jak na przykład poniżej:
Funkcje można trzymać w listach i słownikach tak, jak inne zmienne. Dzięki temu możliwe jest np pokazane poniżej
podejście do zorganizowania bloku decyzyjnego (ang dispatch). Najpierw “klasyczne” podejście, z mega-długim
blokiem if ... else:
process_files_dumb.py¶1from sys import argv 2 3def process_files(file_name) : 4 5 if file_name.endswith(".pdb") : 6 print("processing a PDB file: ",file_name) 7 # ... many, many lines of code that are necessary to parse PDB 8 elif file_name.endswith(".fasta") : 9 print("processing a FASTA file: ",file_name) 10 # ... many, many lines of code that are necessary to parse FASTA 11 elif file_name.endswith(".aln") : 12 print("processing MSA data in ALN format from file: ",file_name) 13 # ... many, many lines of code that are necessary to parse ALN 14 else: 15 print("Unknown file format: ", file_name) 16 17if __name__ == "__main__" : 18 for fname in argv[1:] : process_files(fname) 19
A teraz ze słownikiem funkcji:
process_files.py¶1from sys import argv 2from os.path import splitext 3 4# Actually, thi function may be impored from a separate module devised for PDB processing 5def process_pdb(file_name) : 6 print("processing a PDB file: ",file_name) 7 # ... many, many lines of code that are necessary to parse PDB 8 9def process_fasta(file_name) : # Also might be imported 10 print("processing a FASTA file: ",file_name) 11 # ... many, many lines of code that are necessary to parse FASTA 12 13def process_aln(file_name) : # Also might be imported 14 print("processing MSA data in ALN format from file: ",file_name) 15 # ... many, many lines of code that are necessary to parse ALN 16 17dispatch = { ".pdb" : process_pdb, ".fasta" : process_fasta, ".aln" : process_aln } 18 19if __name__ == "__main__" : 20 for fname in argv[1:] : 21 name, extension = splitext(fname) 22 if extension in dispatch : dispatch[extension](fname) 23 else : print("Unknown file format: ",extension) 24