3. Nieformalne wprowadzenie do Pythona
**************************************

W nadchodzących przykładach wejście i wyjście są rozróżniane przez
obecność lub nieobecność promptów (*>>>* i *...*): aby powtórzyć
przykład, musisz wpisać wszystko po prompcie, kiedy prompt jest
widoczny; linie, które nie zaczynają się promptem są wyjściem z
interpretera. Zwróć uwagę, że prompt drugiego rzędu z pustą linią w
przykładzie oznacza, że musisz wpisać pustą linię; używa się tego do
zakończenia wielo-liniowej komendy.

Wiele przykładów w tej instrukcji, także tych wpisywanych w konsoli
interaktywnej, zawiera komentarze. Komentarze w Pythonie zaczynają się
znakiem hash "#" i ciągną się do końca fizycznej linii. Komentarz może
pojawić się na początku linii, po wiodących spacjach lub kodzie, lecz
nie może być zawarty w literale ciągu znaków. Znak hash w ciągu znaków
jest po prostu znakiem hash. Jako że komentarze mają wyjaśniać kod i
nie są interpretowane przez Pythona, można je ominąć przy wpisywaniu
przykładów.

Trochę przykładów:

   # this is the first comment
   spam = 1  # and this is the second comment
             # ... and now a third!
   text = "# This is not a comment because it's inside quotes."


3.1. Używanie Pythona jako kalkulatora
======================================

Wypróbujmy parę prostych poleceń Pythona. Uruchom interpreter i
poczekaj na pojawienie się pierwszego znaku zachęty ">>>". (Nie
powinno to zająć dużo czasu.)


3.1.1. Liczby
-------------

Interpreter działa jak prosty kalkulator: można wpisać do niego
wyrażenie, a on wypisze jego wartość. Składnia wyrażenia jest prosta:
operatory "+", "-", "*" i "/" można użyć do arytmetyki; nawiasy ("()")
można użyć do grupowania. Na przykład:

   >>> 2 + 2
   4
   >>> 50 - 5*6
   20
   >>> (50 - 5*6) / 4
   5.0
   >>> 8 / 5  # division always returns a floating point number
   1.6

Liczby całkowite (np. "2", "4", "20") są typu "int", te z częścią
ułamkową (np. "5.0", "1.6") są typu "float". Więcej o typach
numerycznych dowiemy się więcej później w tym tutorialu.

Dzielenie ("/") zawsze zwraca liczbę zmiennoprzecinkową. Aby zrobić
*dzielenie całkowite* i uzyskać wynik całkowity możesz użyć operatora
"//"; aby obliczyć resztę możesz użyć "%":

   >>> 17 / 3  # classic division returns a float
   5.666666666666667
   >>>
   >>> 17 // 3  # floor division discards the fractional part
   5
   >>> 17 % 3  # the % operator returns the remainder of the division
   2
   >>> 5 * 3 + 2  # floored quotient * divisor + remainder
   17

W Pythonie możesz użyć operatora "**", do obliczania potęgowania [1]:

   >>> 5 ** 2  # 5 squared
   25
   >>> 2 ** 7  # 2 to the power of 7
   128

Znak równości ("=") jest używany do przypisania wartości do zmiennej.
Przypisanie do zmiennej nie jest wypisywane przez interpreter:

   >>> width = 20
   >>> height = 5 * 9
   >>> width * height
   900

Jeśli zmienna nie jest „zdefiniowana” (nie ma przypisanej wartości),
próba jej użycia spowoduje błąd:

   >>> n  # try to access an undefined variable
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   NameError: name 'n' is not defined

Python implementuje w pełni arytmetykę zmiennoprzecinkową; operatory z
operandami typów mieszanych przekształcają operandy całkowite w
zmiennoprzecinkowe:

   >>> 4 * 3.75 - 1
   14.0

W trybie interaktywnym ostatnie wyświetlone wyrażenie jest
przypisywane do zmiennej "_". Dzięki temu kiedy używasz Pythona jako
biurkowego kalkulatora, jest nieco prościej kontynuować obliczenia, na
przykład:

   >>> tax = 12.5 / 100
   >>> price = 100.50
   >>> price * tax
   12.5625
   >>> price + _
   113.0625
   >>> round(_, 2)
   113.06

Ta zmienna powinna być traktowana przez użytkownika jako tylko-do-
odczytu. Nie przypisuj wprost do niej wartości --- stworzyłbyś
niezależną zmienną lokalną o tej samej nazwie maskując wbudowaną
zmienną z jej magicznym zachowaniem.

Oprócz "int" i "float", Python wspiera inne typy liczb, takie jak
"Decimal" i "Fraction". Python ma też wbudowane wsparcie dla liczb
zespolonych i używa sufiksów "j" lub "J" do wskazania części urojonej
(np. "3+5j").


3.1.2. Tekst
------------

Python umożliwia manipulację tekstem (reprezentowanym przez typ "str",
tzw. „ciąg znaków” lub „string”) oraz liczbami. Obejmuje to znaki
„"!"”, słowa „"królik"”, nazwy „"Paryż"”, zdania „"Możesz na mnie
liczyć."”, itp. „"Hurra! :)"”. Mogą być one umieszczone w pojedynczych
cudzysłowach ("'...'") lub podwójnych cudzysłowach (""..."") z takim
samym wynikiem [2].

>>> 'spam eggs'  # single quotes
'spam eggs'
>>> "Paris rabbit got your back :)! Yay!"  # double quotes
'Paris rabbit got your back :)! Yay!'
>>> '1975'  # digits and numerals enclosed in quotes are also strings
'1975'

Aby umieścić znak cudzysłowu, musimy go oznaczyć znakiem "ucieczki",
poprzedzając znakiem "\". Alternatywnie, możemy użyć innego rodzaju
znaków do oznaczenia cudzysłowu:

   >>> 'doesn\'t'  # use \' to escape the single quote...
   "doesn't"
   >>> "doesn't"  # ...or use double quotes instead
   "doesn't"
   >>> '"Yes," they said.'
   '"Yes," they said.'
   >>> "\"Yes,\" they said."
   '"Yes," they said.'
   >>> '"Isn\'t," they said.'
   '"Isn\'t," they said.'

W interaktywnej powłoce Pythona definicja ciągu znaków i wyjściowy
ciąg znaków mogą wyglądać inaczej. Funkcja "print()" wytwarza czytelne
wyjście, poprzez pominięcie otaczających cudzysłowów, pominięcie
znaków ucieczki i wypisanie znaków specjalnych:

   >>> s = 'First line.\nSecond line.'  # \n means newline
   >>> s  # without print(), special characters are included in the string
   'First line.\nSecond line.'
   >>> print(s)  # with print(), special characters are interpreted, so \n produces new line
   First line.
   Second line.

Jeśli nie chcesz, aby znaki poprzedzone "\" były interpretowane jako
znaki specjalne, możesz użyć *surowych ciągów znaków* (ang. *raw
strings*) dodając "r" przed pierwszym cudzysłowem:

   >>> print('C:\some\name')  # here \n means newline!
   C:\some
   ame
   >>> print(r'C:\some\name')  # note the r before the quote
   C:\some\name

Istnieje jeden subtelny aspekt surowych ciągów znaków: surowy ciąg
znaków nie może kończyć się nieparzystą liczbą znaków "\"; zobacz wpis
FAQ, aby uzyskać więcej informacji i sposobów obejścia tego problemu.

Literały ciągów znaków mogą mieć wiele linii. Można je uzyskać
używając potrójnych cudzysłowów: """"…"""" lub "'''…'''". Końce linii
są automatycznie zawarte w ciągu znaków, ale można tego uniknąć
dodając "\" na końcu linii. Następujący przykład:

   print("""\
   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to
   """)

produkuje następujące wyjście (zwróć uwagę, że nie ma pierwszej nowej
linii):

   Usage: thingy [OPTIONS]
        -h                        Display this usage message
        -H hostname               Hostname to connect to

Ciągi mogą być łączone operatorem "+" i powtarzane przy użyciu "*":

   >>> # 3 times 'un', followed by 'ium'
   >>> 3 * 'un' + 'ium'
   'unununium'

Dwa lub więcej *literały ciągu znaków* (czyli te zawarte w
cudzysłowach) obok siebie są automatycznie łączone.

   >>> 'Py' 'thon'
   'Python'

To zachowanie jest szczególnie przydatne, gdy chcesz dzielić długie
ciągi:

   >>> text = ('Put several strings within parentheses '
   ...         'to have them joined together.')
   >>> text
   'Put several strings within parentheses to have them joined together.'

Jednak działa tylko dla literałów, nie dla zmiennych lub wyrażeń:

   >>> prefix = 'Py'
   >>> prefix 'thon'  # can't concatenate a variable and a string literal
     File "<stdin>", line 1
       prefix 'thon'
              ^^^^^^
   SyntaxError: invalid syntax
   >>> ('un' * 3) 'ium'
     File "<stdin>", line 1
       ('un' * 3) 'ium'
                  ^^^^^
   SyntaxError: invalid syntax

Jeśli chcesz połączyć zmienne lub zmienną i literał, użyj "+":

   >>> prefix + 'thon'
   'Python'

Ciągi znaków mogą być *indeksowane*. Pierwszy znak ma indeks 0. Nie ma
osobnego typu znakowego; znak jest po prostu ciągiem znaków o długości
jeden:

   >>> word = 'Python'
   >>> word[0]  # character in position 0
   'P'
   >>> word[5]  # character in position 5
   'n'

Indeksy mogą być też liczbami ujemnymi, aby zacząć odliczać od prawej:

   >>> word[-1]  # last character
   'n'
   >>> word[-2]  # second-last character
   'o'
   >>> word[-6]
   'P'

Zwróć uwagę, że jako -0 to to samo co 0, ujemne indeksy zaczynają się
od -1.

In addition to indexing, *slicing* is also supported.  While indexing
is used to obtain individual characters, *slicing* allows you to
obtain substring:

   >>> word[0:2]  # characters from position 0 (included) to 2 (excluded)
   'Py'
   >>> word[2:5]  # characters from position 2 (included) to 5 (excluded)
   'tho'

Indeksy podzielonych fragmentów mają przydatne wartości domyślne;
pominięty pierwszy indeks domyślnie jest zerem, pominięty drugi indeks
domyślnie ma wartość długości dzielonego stringa.

   >>> word[:2]   # character from the beginning to position 2 (excluded)
   'Py'
   >>> word[4:]   # characters from position 4 (included) to the end
   'on'
   >>> word[-2:]  # characters from the second-last (included) to the end
   'on'

Zwróć uwagę, że początkowy indeks wchodzi w skład podciągu, a końcowy
nie. W ten sposób "s[:i] + s[i:]" jest zawsze równe "s":

   >>> word[:2] + word[2:]
   'Python'
   >>> word[:4] + word[4:]
   'Python'

Jednym ze sposobów na zapamiętanie, jak działa podział, to myślenie o
indeksach wskazujących *pomiędzy* znakami, z lewą krawędzią pierwszego
znaku numerowaną 0. Wtedy prawa krawędź ostatniego znaku ciągu o
długości *n* ma indeks *n*, na przykład:

    +---+---+---+---+---+---+
    | P | y | t | h | o | n |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
   -6  -5  -4  -3  -2  -1

W pierwszym wierszu liczb są pozycje indeksów od 0 do 6 w ciągu. W
drugim wierszu odpowiadające im indeksy ujemne. Fragment od *i* do *j*
składa się ze wszystkich znaków pomiędzy krawędziami oznaczonymi
kolejno *i* i *j*.

Dla nieujemnych indeksów długość wydzielonego fragmentu to różnica
indeksów, jeśli oba mieszczą się w zakresie. Na przykład długość
"word[1:3]" to 2.

Próba użycia za dużego indeksu skończy się błędem:

   >>> word[42]  # the word only has 6 characters
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   IndexError: string index out of range

Jednak indeksy podzielonych fragmentów poza zakresem są obsłużone
bezpiecznie przy podziale:

   >>> word[4:42]
   'on'
   >>> word[42:]
   ''

Ciągi znaków Pythona nie mogą być zmieniane — są *niemutowalne*. W
związku z tym przypisywanie wartości do indeksowanej pozycji w ciągu
spowoduje błąd:

   >>> word[0] = 'J'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment
   >>> word[2:] = 'py'
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'str' object does not support item assignment

Jeśli potrzebujesz innego ciągu znaków, powinieneś(-nnaś) stworzyć
nowy:

   >>> 'J' + word[1:]
   'Jython'
   >>> word[:2] + 'py'
   'Pypy'

Wbudowana funkcja "len()" zwraca długość ciągu:

   >>> s = 'supercalifragilisticexpialidocious'
   >>> len(s)
   34

Zobacz także:

  Text Sequence Type --- str
     Ciągi znaków są przykładami *typów sekwencyjnych* i obsługują
     wspólne operacje wspierane przez takie typy.

  Metody ciągów
     Ciągi znaków wspierają dużą liczbę metod do podstawowych
     przekształceń i wyszukiwania.

  f-strings
     Literały ciągów znaków z osadzonymi wyrażeniami.

  Format String Syntax
     Informacje o formatowaniu ciągów znaków przy użyciu
     "str.format()".

  printf-style String Formatting
     Stare operacje formatowania, wywoływane gdy ciągi znaków są
     lewymi operandami operatora "%" są opisane tutaj bardziej
     szczegółowo.


3.1.3. Listy
------------

Python ma kilka *złożonych* typów danych, używanych do grupowania
różnych wartości. Najbardziej wszechstronnym jest *lista*, która może
zostać zapisana jako lista wartości (elementów) rozdzielonych
przecinkami ujęta w nawiasy kwadratowe. Listy mogą zawierać elementy
różnych typów, ale zazwyczaj wszystkie elementy mają ten sam typ.

   >>> squares = [1, 4, 9, 16, 25]
   >>> squares
   [1, 4, 9, 16, 25]

Tak jak ciągi znaków (i wszystkie inne wbudowane typy *sekwencyjne*),
do elementów list można odwoływać się przez indeksy oraz można z nich
„wydzielać”:

   >>> squares[0]  # indexing returns the item
   1
   >>> squares[-1]
   25
   >>> squares[-3:]  # slicing returns a new list
   [9, 16, 25]

Listy wspierają też operacje takie jak łączenie:

   >>> squares + [36, 49, 64, 81, 100]
   [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

W przeciwieństwie do ciągów znaków, które są *niemutowalne*, listy są
typem *mutowalnym*, w szczególności można zmieniać ich treść:

   >>> cubes = [1, 8, 27, 65, 125]  # something's wrong here
   >>> 4 ** 3  # the cube of 4 is 64, not 65!
   64
   >>> cubes[3] = 64  # replace the wrong value
   >>> cubes
   [1, 8, 27, 64, 125]

Można również dodawać nowe elementy na końcu listy, przez użycie
*metody* (dowiemy się więcej o metodach później) "list.append()":

   >>> cubes.append(216)  # add the cube of 6
   >>> cubes.append(7 ** 3)  # and the cube of 7
   >>> cubes
   [1, 8, 27, 64, 125, 216, 343]

Proste przypisanie w Pythonie nigdy nie kopiuje danych. Kiedy
przypisujesz listę do zmiennej, zmienna odnosi się do *istniejącej
listy*. Wszystkie zmiany dokonane na liście przez jedną zmienną będą
widoczne przez wszystkie inne zmienne, które się do niej odwołują.:

   >>> rgb = ["Red", "Green", "Blue"]
   >>> rgba = rgb
   >>> id(rgb) == id(rgba)  # they reference the same object
   True
   >>> rgba.append("Alph")
   >>> rgb
   ["Red", "Green", "Blue", "Alph"]

Wszystkie operacje wykrawania zwracają nową listę zawierającą żądane
elementy. Następujący slice więc zwraca płytką kopię listy:

   >>> correct_rgba = rgba[:]
   >>> correct_rgba[-1] = "Alpha"
   >>> correct_rgba
   ["Red", "Green", "Blue", "Alpha"]
   >>> rgba
   ["Red", "Green", "Blue", "Alph"]

Możliwe jest również przypisywanie do slice'ów. Może to zmienić
rozmiar listy lub zupełnie ją wyczyścić:

   >>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> letters
   ['a', 'b', 'c', 'd', 'e', 'f', 'g']
   >>> # replace some values
   >>> letters[2:5] = ['C', 'D', 'E']
   >>> letters
   ['a', 'b', 'C', 'D', 'E', 'f', 'g']
   >>> # now remove them
   >>> letters[2:5] = []
   >>> letters
   ['a', 'b', 'f', 'g']
   >>> # clear the list by replacing all the elements with an empty list
   >>> letters[:] = []
   >>> letters
   []

Wbudowana funkcja "len()" ma również zastosowanie do list:

   >>> letters = ['a', 'b', 'c', 'd']
   >>> len(letters)
   4

Można zagnieżdżać listy (tworzyć listy zawierające inne listy), na
przykład:

   >>> a = ['a', 'b', 'c']
   >>> n = [1, 2, 3]
   >>> x = [a, n]
   >>> x
   [['a', 'b', 'c'], [1, 2, 3]]
   >>> x[0]
   ['a', 'b', 'c']
   >>> x[0][1]
   'b'


3.2. Pierwsze kroki do programowania
====================================

Oczywiście możemy używać Pythona do zadań bardziej skomplikowanych niż
dodawanie dwóch do dwóch. Na przykład możemy napisać początkowy
podciąg ciągu Fibonacciego następująco:

   >>> # Fibonacci series:
   ... # the sum of two elements defines the next
   ... a, b = 0, 1
   >>> while a < 10:
   ...     print(a)
   ...     a, b = b, a+b
   ...
   0
   1
   1
   2
   3
   5
   8

Ten przykład wprowadza kilka nowych funkcji.

* Pierwsza linia zawiera *wielokrotne przypisanie*: zmienne "a" i "b"
  jednocześnie dostają nowe wartości 0 i 1. W ostatniej linii jest
  ponownie wykorzystane, demonstrując, że wyrażenia po prawej stronie
  są ewaluowane wcześniej, zanim którekolwiek z przypisań ma miejsce.
  Wyrażenia po prawej stronie są ewaluowane od lewej do prawej.

* Pętla "while" wykonuje się dopóki warunek (tutaj: "a < 10")
  pozostaje prawdziwy. W Pythonie, tak jak w C, każda niezerowa liczba
  całkowita jest prawdziwa; zero jest fałszywe. Warunek może być
  również ciągiem znaków lub listą, tak naprawdę jakąkolwiek
  sekwencją; cokolwiek o niezerowej długości jest prawdziwe, puste
  sekwencje są fałszywe. Warunek użyty w przykładzie jest prostym
  porównaniem. Standardowe operatory porównań pisane są tak samo jak w
  C: "<" (mniejsze niż), ">" (większe niż), "==" (równe), "<="
  (mniejsze lub równe), ">=" (większe lub równe) i "!=" (różne).

* *Ciało* pętli jest *wcięte*: indentacja (wcięcia) jest sposobem na
  grupowanie instrukcji. W trybie interaktywnym trzeba wprowadzić
  znak(i) spacji lub tabulacji, aby wciąć wiersz. W praktyce będziesz
  przygotowywać bardziej skomplikowane dane wejściowe dla Pythona za
  pomocą edytora tekstu; wszystkie przyzwoite edytory tekstu mają
  funkcję automatycznych wcięć. W chwili, gdy wprowadza się jakąś
  instrukcję złożoną w czasie sesji interpretera Pythona, trzeba
  zakończyć ją pustym wierszem (bowiem interpreter nie wie, czy
  ostatni wprowadzony wiersz jest ostatnim z tej instrukcji). Ważne
  jest, aby każdy wiersz należący do tej samej grupy instrukcji, był
  wcięty o taką samą liczbę spacji lub znaków tabulacji.

* Funkcja "print()" wypisuje wartość argumentu(-ów), które jej podano.
  Różnica pomiędzy tą instrukcją, a zwykłym zapisem wyrażenia, które
  chce się wypisać (tak jak robiliśmy to w przykładzie z kalkulatorem)
  występuje w sposobie obsługi wielu wyrażeń i napisów. Łańcuchy
  znaków wypisywane są bez cudzysłowów, a pomiędzy nimi zapisywane są
  spacje, tak aby można było ładnie sformatować pojawiający się napis,
  na przykład:

     >>> i = 256*256
     >>> print('The value of i is', i)
     The value of i is 65536

  Keyword argument *end* można wykorzystać, aby uniknąć znaku nowej
  linii po wypisaniu lub aby zakończyć wypisanie innym ciągiem znaków:

     >>> a, b = 0, 1
     >>> while a < 1000:
     ...     print(a, end=',')
     ...     a, b = b, a+b
     ...
     0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

-[ Przypisy ]-

[1] Jako że "**" ma wyższą precedencję niż "-", "-3**2" zostanie
    zinterpretowane jako "-(3**2)" i zwróci "-9". Aby tego uniknąć i
    otrzymać "9", możesz użyć "(-3)**2".

[2] W przeciwieństwie do innych języków, znaki specjalne takie jak
    "\n" mają to samo znaczenie zarówno z pojedynczym ("'…'") jak i
    podwójnym (""…"") cudzysłowem. Jedyną różnicą między nimi jest to,
    że wewnątrz pojedynczego cudzysłowu nie musisz używać znaku
    ucieczki dla """ (lecz musisz użyć znaku ucieczki "\'") i vice
    versa.
