Zanurkuj w Pythonie/Potęga introspekcji: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Piotr (dyskusja | edycje)
tłumaczenie
Piotr (dyskusja | edycje)
m usunięcie przeniesionej części
Linia 6:
nast=Obiekty i klasy}}
------------
 
__TOC__
== Nurkujemy ==
W tym rozdziale dowiesz się o jednej z właściwości Pythona: '''introspekcji'''. Jak już wiesz, wszystko w Pythonie jest obiektem a introspekcja to kod, którego zadaniem jest obserwacja innych modułów i funkcji w pamięci jako obiektów, pobieranie informacji o nich oraz operowanie nimi.
 
Linia 61 ⟶ 62:
Returns string.
 
==Użycie argumentów opcjonalnych i "nazwanych"==
 
Python pozwala argumentom funkcji posiadać wartości domyślne. Jeżeli funkcja jest wywoływana bez argumentów, przypisywane są im wartości zdefiniowane jako domyślne. Co więcej, argumenty mogą być określone poprzez użycie ich nazw.
 
Poniżej przykład funkcji <tt>info</tt> z dwoma argumentami opcjonalnymi:
 
def info(object, spacing=10, collapse=1):
 
<tt>spacing</tt> oraz <tt>collapse</tt> są opcjonalne, ponieważ mają przypisane wartości domyślne. <tt>object</tt> jest wymagany, ponieważ nie posiada wartości domyślnej. Jeżeli <tt>info</tt> jest wywoływane z tylko jednym argumentem, <tt>spacing</tt> przyjmuje wartości 10 a <tt>collapse</tt> 1. Jeżeli wywołamy tę funkcję z dwoma argumentami, tylko <tt>collapse</tt> przyjmuje wartość domyślną (w tym przypadku 1).
 
Powiedzmy, że chcesz określić wartość dla <tt>collapse</tt>, ale także chcesz przyjąć wartość domyślną dla <tt>spacing</tt>. W większości języków ta sztuczka nie uda się, ponieważ będziesz zmuszony do wywołania funkcji z trzema argumentami. Ale w Pythonie argumenty można określać poprzez ich nazwę, w jakiejkolwiek kolejności.
 
Przykład 4.4. Poprawne wywołania funkcji <tt>info</tt>
 
info(odbchelper) #(1)
info(odbchelper, 12) #(2)
info(odbchelper, collapse=0) #(3)
info(spacing=15, object=odbchelper) #(4)
 
#Z jednym argumentem, <tt>spacing</tt> przyjmuje wartość domyślną (10) a <tt>collapse</tt> wartość 1.
#Z dwoma argumentami, <tt>collapse</tt> przyjmuje wartość domyślną, czyli 1.
#Tutaj wywołujemy argument <tt>collapse</tt> podając jego nazwę i wartość, którą chcemy mu przypisać. <tt>spacing</tt> przyjmuje wartość domyślną, czyli w tym przypadku 10.
#Nawet wymagany argument (jak <tt>object</tt> w tym przypadku, który nie posiada wartości domyślnej) może być określony poprzez swoją nazwę i może wystapić na jakimkolwiek miejscu w wywołaniu funkcji.
 
To może być trochę niejasne dopóki nie zdasz sobie sprawy, że lista argumentów jest po prostu słownikiem. Gdy wywołujesz funkcje "normalnie", czyli bez podawania nazw argumentów, Python dopasowuje wartości do określonych argumentów w takiej kolejności w jakiej zostały zadeklarowane. Najczęściej będziesz wykorzystywał tylko "normalne" wywołania funkcji, ale zawsze masz możliwość bardziej elastycznego podejścia do określania kolejności argumentów.
 
{{infobox|tekst=Jedyną rzeczą, którą musisz zrobić by poprawnie wywołać funkcję, jest w jakikolwiek sposób określić wartość dla każdego wymaganego argumentu. Sposób i kolejność określania argumentów zależy tylko od Ciebie.}}
 
== Użycie type, str, dir i innych wbudowanych funkcji ==
 
Python posiada mały zbiór bardzo użytecznych, wbudowanych funkcji. Wszystkie inne funkcje są podzielone na moduły. Podobnie wygląda w przypadku innych języków skryptowych (jak Visual Basic).
 
=== Funkcja <tt>type</tt> ===
Funkcja <tt>type</tt> zwraca typ danych podanego obiektu. Możliwe typy znajdują się w module <tt>types</tt>. To jest pomocne w przypadku funkcji pomocy, która może obejmować różne typy danych.
 
'''Przykład 4.5. Przedstawienie <tt>type</tt>'''
 
>>> type(1) #(1)
<type 'int'>
>>> li = []
>>> type(li) #(2)
<type 'list'>
>>> import odbchelper
>>> type(odbchelper) #(3)
<type 'module'>
>>> import types #(4)
>>> type(odbchelper) == types.ModuleType
True
 
# Argumentem type może być cokolwiek, stałe, łańcuchy znaków, listy, słowniki, krotki, funkcje, klasy, moduły a także typy.
# type może pobrać dowolną zmienną i zwrócić jej typ.
# <tt>type</tt> także działa na modułach.
# Możesz używać stałych z modułu <tt>types</tt>, aby porównywać typy obiektów.
 
=== Funkcja <tt>str</tt> ===
 
Funkcja <tt>str</tt> przekształca dane w łańcuch znaków. Każdy typ danych może zostać przekształcony w łańcuch znaków.
 
'''Przykład 4.6. Przedstawienie do <tt>str</tt>
 
>>> str(1) #(1)
'1'
>>> horsemen = ['war', 'pestilence', 'famine']
>>> horsemen
['war', 'pestilence', 'famine']
>>> horsemen.append('Powerbuilder')
>>> str(horsemen) #(2)
"['war', 'pestilence', 'famine', 'Powerbuilder']"
>>> str(odbchelper) #(3)
"<module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'>"
>>> str(None) #(4)
'None'
 
# Można się spodziewać, że <tt>str</tt> działa na tych prostych, podstawowych typach takich jak np. liczby całkowite; prawie każdy język programowania posiada funkcję konwertującą tekst na łańcuch znaków.
# Jakkolwiek funkcja <tt>str</tt> pracuje na każdym obiekcie dowolnego typu. W tym przypadku jest to lista składająca się z kilku elementów
# Jako argument w funkcji <tt>str</tt> możemy podać także moduł. Zauważ, że łańcuch reprezentujący moduł zawiera ścieżkę do miejsca, w którym się ten moduł znajduje. Na różnych komputerach może być ona inna.
# Subtelnym, lecz ważnym zachowaniem funkcji <tt>str</tt> jest to, że argumentem może być nawet wartość <tt>None</tt> (odpowiednik Pythonowej wartości pustej, często nazywanej w innych językach <tt>null</tt>). Dla takiego argumentu funkcja zwraca tekst <tt>'None'</tt>. Wkrótce wykorzystamy tę możliwość.
 
=== Funkcja <tt>dir</tt> ===
 
Kluczową funkcją wykorzystaną w <tt>info</tt> jest funkcja <tt>dir</tt>. Funkcja ta zwraca listę atrybutów i metod pewnego obiektu czyli, może to być moduł, funkcja, łańcuch znaków, lista, słownik... niemal wszystko.
 
'''Przykład 4.7. Wprowadzenie do <tt>dir</tt>'''
 
>>> li = []
>>> dir(li) #(1)
['append', 'count', 'extend', 'index', 'insert',
'pop', 'remove', 'reverse', 'sort']
>>> d = {}
>>> dir(d) #(2)
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
>>> import odbchelper
>>> dir(odbchelper) #(3)
['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']
 
# <tt>li</tt> jest listą, dlatego też <tt>dir(li)</tt> zwróci nam listę wszystkich metod, które posiada lista. Zwróćmy uwagę na to, że zwracana lista zawiera nazwy metod w formie lańcucha znaków, a nie same funkcje.
# <tt>d</tt> jest słownikiem, dlatego <tt>dir(d)</tt> zwróci listę nazw metod słownika. Co najmniej jednach z nich -- <tt>keys</tt> powinna wyglądać znajomo.
# Dzięki temu funkcja ta staje się interesująca. <tt>odbchelper</tt> jest modułem, tak więc dzięki <tt>dir(odbchelper)</tt> otrzymamy listę wszyskich „dzieci” zdefiniowanych w tym module, dołączając wbudowane atrybuty takie jak <tt>__name__</tt>, czy też <tt>__doc__</tt> i jakiekolwiek inne atrybuty i metody zdefiniowane przez nas. W tym przypadku <tt>odbchelper</tt> posiada tylko jedną, zdefiniowaną przez użytkownika metodę -- funkcję <tt>buildConnectionString</tt> opisaną w [[Python:Wbudowane typy danych|Rozdziale 2]].
 
Funkcja <tt>callable</tt> zwraca True, jeśli podany obiekt może być wywołany, a False w przeciwnym przypadku. Wykonywalne obiekty, włączając w to funkcje, metody klas i nawet same klasy. (Wiecej o klasach możemy przeczytać w [[Python:Obiekty i klasy|następnym rozdziale]].)
 
'''Przykład 4.8. Wprowadzenie do funkcji <tt>callable</tt>'''
 
>>> import string
>>> string.punctuation #(1)
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> string.join #(2)
<function join at 00C55A7C>
>>> callable(string.punctuation) #(3)
False
>>> callable(string.join) #(4)
True
>>> print string.join.__doc__ #(5)
join(list [,sep]) -> string
 
Return a string composed of the words in list, with
intervening occurrences of sep. The default separator is a
single space.
(joinfields and join are synonymous)
 
# Zaleca się, żeby funkcje z modułu string nie były używane (są w stanie „deprecated”) (chociaż wciąż wiele osób używa funkcji <tt>join</tt>), lecz moduł ten zawiera wiele przydatnych stałych jak np. <tt>string.punctuation<?tt>, który przechowuje wszystkie standardowe znaki przystankowe.
# Funkcja <tt>string.join</tt> łączy listę w tekst.
# <tt>string.punctuation</tt> nie jest wywoływalny, jest łańcuchem znaków. (Typ <tt>string</tt> posiada wywoływalne metody, lecz sam nie jest wywoływalny.)
# <tt>string.join</tt> jest wywoływalny, jest to funkcja biorąca dwa argumenty.
# Każdy wywoływalny obiekt może posiadać notkę dokumentacyjną. Używając funkcji <tt>callable</tt> na każdym atrybucie obiektu, możemy określić o których atrybutach będziemy mogli się czegoś dowiedzieć (metody, funkcje, klasy) i pominąć te (stałe itp.), o których się nic nie dowiemy.
 
=== Wbudowane funkcje ===
 
Funkcje <tt>type</tt>, <tt>str</tt>, <tt>dir</tt> i wszystkie pozostałe wbudowane funkcje wbudowane są umieszczone w specialnym module nazwanym <tt>__builtin__</tt> (Nazwa z dwoma podkreśleniami przed i po nazwie). Jeśli to pomoże, możesz założyć, że Python automatycznie wykonuje przy starcie polecenie <tt>from __builtin__ import *</tt>, które importuje wszystkie wbudowane funkcje do przestrzeni nazw używanej bezpośrednio przez nas.
 
Zaletą tego jest to, że możemy dostać informacje o wszystkich wbudowanych funkcjach i atrybutach poprzez moduł <tt>__builtin__</tt>. Wypróbujmy wcześniej napisaną przez nas funkcję <tt>info</tt> i przeglądnijmy utworzoną listę. Niektóre bardziej ważne funkcje zglębimy później. (Niektóre z wbudowanych klasy błędów np. AttributeError, powinny wyglądać znajomo.)
 
'''Przykład 4.9. Wbudowane atrybuty i funkcje'''
 
>>> from apihelper import info
>>> import __builtin__
>>> info(__builtin__, 20)
ArithmeticError Base class for arithmetic errors.
AssertionError Assertion failed.
AttributeError Attribute not found.
EOFError Read beyond end of file.
EnvironmentError Base class for I/O related errors.
Exception Common base class for all exceptions.
FloatingPointError Floating point operation failed.
IOError I/O operation failed.
[...snip...]
 
{{Infobox|
Wraz z Pythonem dostajesz doskonałą dokumentajcę, zawierającą wszystkie potrzebne informacje o modułach oferowanych przez ten język. W porównaniu do innych języków programowania, tutaj nie dostajesz podręcznika <tt>man</tt>, czy odwołań do innych zewnętrznych podręczników, wszystko co potrzebujesz znajdziesz wewnątrz samego Pythona.
}}
 
=== Otrzymywanie referencji obiektu ===
 
Powinniśmy już wiedzieć, że w Pythonie funkcje są także obiektami. Nie dowiedzieliśmy się tego, że możemy dostać referencję do funkcji nie znając jej nazwy przed uruchomieniem programu. Należy w tym celu wykorzystać funkcję <tt>getattr</tt>.
 
''' Przykład 4.10. Przedstawienie funkcji <tt>getattr</tt> '''
 
>>> li = ["Larry", "Curly"]
>>> li.pop #(1)
<built-in method pop of list object at 010DF884>
>>> getattr(li, "pop") #(2)
<built-in method pop of list object at 010DF884>
>>> getattr(li, "append")("Moe") #(3)
>>> li
["Larry", "Curly", "Moe"]
>>> getattr({}, "clear") #(4)
<built-in method clear of dictionary object at 00F113D4>
>>> getattr((), "pop") #(5)
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'pop'
 
# Dzięki temu dostaliśmy referencję do metody listy o nazwie <tt>pop</tt>. Zauważmy, że nie wywołaliśmy metody <tt>pop</tt>, tylko dostaliśmy ją samą. Żeby ją wykonać musilibyśmy napisać <tt>li.pop()</tt>
# Operacja ta także zwróciła referencję do metody <tt>pop</tt>, lecz tym razem nazwa metody jest określone poprzez łańcuch znaków wykorzystany jako argument funkcji <tt>getattr</tt>. <tt>getattr</tt> jest niewiargodnie użyteczną wbudowaną funkcją, która zwraca pewien atrybut dowolnego obiektu. Tym razem wykorzystaliśmy obiekt, który jest listą, a atrybutem jest metoda <tt>pop</tt>.
# Przykład ten pokazuje, jak bardzo przydatna może być ta funkcja. Zwracaną wartością funkcji <tt>getattr</tt> jest metoda. Metodę tę możemy wykonać podobnie jak wykonujemy <tt>li.append("Moe")</tt>. Jednak teraz nie wywułujemy funkcji bezpośrednio, lecz podajemy jej nazwę w postaci łańcucha znaków.
# <tt>getattr</tt> bez problemu pracuje na słownikach
# Teoretycznie <tt>getattr</tt> powinien pracować na krotkach, jednak krotki nie posiadają żadnej metody, dlatego <tt>getattr</tt> spowoduje wystąpienie wyjątku związanego z brakiem atrybutu o podanej nazwie.
 
{{ProstaNawigacja|