Zanurkuj w Pythonie/Potęga introspekcji

W tym rozdziale dowiemy się o jednej z mocnych stron Pythona -- introspekcji. Jak już wiemy, wszystko w Pythonie jest obiektem, natomiast introspekcja jest kodem, który postrzega funkcje i moduły znajdujące się w pamięci jako obiekty, a także pobiera o nich informacje i operuje nimi.

Nurkujemy

edytuj

Zacznijmy od kompletnego, działającego programu. Przeglądając kod na pewno rozumiesz już niektóre jego fragmenty. Przy niektórych liniach znajdują się liczby w komentarzach; korzystamy tu z koncepcji, które wykorzystywaliśmy już w rozdziale drugim. Nie przejmuj się, jeżeli nie rozumiesz części tego programu. W rozdziale tym wszystkiego się jeszcze nauczysz.

Przykład. apihelper.py
def info(object, spacing=10, collapse=1): #(1) (2) (3)
    u"""Wypisuje metody i ich notki dokumentacyjne.

    Argumentem może być moduł, klasa, lista, słownik, czy też łańcuch znaków."""
    methodList = [method for method in dir(object) if callable(getattr(object, method))]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
    print ("\n".join(["%s %s" %
                  (method.ljust(spacing),
                   processFunc(unicode(getattr(object, method).__doc__)))
                 for method in methodList]))
if __name__ == "__main__":    #(4) (5)
    print (info.__doc__)
  1. Ten moduł ma jedną funkcję info. Zgodnie ze swoją deklaracją wymaga ona trzech argumentów: object, spacing oraz collapse. Dwa ostatnie parametry są opcjonalne, co za chwilę zobaczymy.
  2. Funkcja info posiada wieloliniową notkę dokumentacyjną, która opisuje jej zastosowanie. Zauważ, że funkcja nie zwraca żadnej wartości. Ta funkcja będzie wykorzystywana, aby wykonać pewną czynność, a nie żeby otrzymać pewną wartość.
  3. Kod wewnątrz funkcji jest wcięty.
  4. Sztuczka z if __name__ pozwala wykonać programowi coś użytecznego, kiedy zostanie uruchomiony samodzielnie. Jeśli powyższy kod zaimportujemy jako moduł do innego programu, kod pod tą instrukcją nie zostanie wykonany. W tym wypadku program wypisuje po prostu notkę dokumentacyjną funkcji info.
  5. Instrukcja if wykorzystuje == (dwa znaki równości), aby porównać dwie wartości. W instrukcji if nie musimy korzystać z nawiasów okrągłych.

Funkcja info została zaprojektowana tak, aby ułatwić sobie pracę w IDE Pythona. IDE bierze jakiś obiekt, który posiada funkcje lub metody (jak na przykład moduł zawierający funkcje lub listę, która posiada metody) i wyświetla funkcje i ich notki dokumentacyjne.

Przykład. Proste zastosowanie apihelper.py
>>> from apihelper import info
>>> li = []
>>> info(li)

[...ciach...] append L.append(object) -- append object to end count L.count(value) -> integer -- return number of occurrences of value extend L.extend(iterable) -- extend list by appending elements from the iterable index L.index(value, [start, [stop]]) -> integer -- return first index of value insert L.insert(index, object) -- insert object before index pop L.pop([index]) -> item -- remove and return item at index (default last) remove L.remove(value) -- remove first occurrence of value reverse L.reverse() -- reverse *IN PLACE* sort L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*; cmp(x, y) -> -1, 0, 1

Domyślnie wynik jest formatowany tak, by był łatwy do odczytania. Notki dokumentacyjne składające się z wielu linii zamieniane są na jednoliniowe, ale tę opcję możemy zmienić ustawiając wartość 0 dla argumentu collapse. Jeżeli nazwa funkcji jest dłuższa niż 10 znaków, możemy określić inną wartość dla argumentu spacing, by ułatwić sobie czytanie.

Przykład. Zaawansowane użycie apihelper.py
>>> import odbchelper
>>> info(odbchelper)
buildConnectionString Tworzy łańcuchów znaków na podstawie słownika parametrów. Zwraca łańcuch znaków.
>>> info(odbchelper, 30)
buildConnectionString          Tworzy łańcuchów znaków na podstawie słownika parametrów. Zwraca łańcuch znaków.
>>> info(odbchelper, 30, 0)

buildConnectionString Tworzy łańcuchów znaków na podstawie słownika parametrów. Zwraca łańcuch znaków.