Łańcuchy znaków w Pythonie
Podstawowe typy zmiennych oraz zasady ich nazewnictwa już opisałem, ale to nie wszystko – zwłaszcza w przypadku zmiennych typu string – stąd osobny wpis im poświęcony. I nie skończy się na jednym:)

Wyświetlanie łańcuchów
Łańcuch znaków, wspomniana w poprzednich notkach zmienna typu string to po prostu ciąg znaków w zadanej kolejności, przechowywany w pamięci pod konkretną nazwą. Łańcuch podajemy w pojedynczych lub podwójnych cudzysłowach:
>>> print("Tekst")
Tekst
>>> print('Tekst')
Tekst
Pewnie pierwsze pytanie jakie Ci się nasuwa – a jak w takim razie wyświetlić jeden znak apostrofu? Jeżeli znasz już inne języki, to może wiesz o „znakach ucieczki” (escape characters). Otóż można dodać backslash (zwany odwróconym ukośnikiem lub „za moich czasów” odwróconą kreskę ułamkową) i po nim znak cudzysłowu. Zostanie on wtedy potraktowany jak każdy inny znak, a nie zamknięcie stringa. Albo – ponieważ j- łańcuch musi być otoczony takimi samymi znakami – albo pojedyncze cudzysłowy, albo podwójne – można „ten inny” wpleść pomiędzy. Ale znaków otwarcia i zamknięcia łańcucha nie mieszamy!
>>> print("Don't cry")
Don't cry
>>> print('Don\'t cry')
Don't cry
>>>print('W kinie grają "Batmana" od jutra')
W kinie grają "Batmana" od jutra
>>> print('W kinie grają \'Batmana\' od jutra')
W kinie grają 'Batmana' od jutra
Oczywiście jak to w Pythonie – żeby nie było nudno – można jeszcze używać potrójnych cudzysłowów. Do dzielenia łańcucha między wiersze na ekranie (nikt nie lubi czytać tasiemców przewijając ekran w bok).
>>> print("""Napisać
wiersz
w ten sposób
można""")
Napisać
wiersz
w ten sposób
można
To właśnie ze względu na to, że w Pythonie nie wyodrębniamy kawałków kodu średnikiem i nawiasami klamrowymi jak w C czy Javie, a wcięciami – dzięki potrójnym cudzysłowom ewentualne wcięcia wewnątrz łańcucha będą ignorowane).
Teraz jeszcze w drugą stronę – możemy w kodzie przypisanie długiego łańcucha rozbić na kilka wierszy dla lepszej czytelności – pamiętaj tylko, żeby całość wziąć w nawias (to, że finalnie będzie jednym łańcuchem czasami jest zaletą – np. gdy wyświetlamy tekst w okienku o zmiennej szerokości).
>>> tekst = ('Piszemy sobie kilka linijek '
'i rozbijamy na kilka wierszy - '
'pamiętając o spacjach;)')
>>> print(tekst)
Piszemy sobie kilka linijek i rozbijamy na kilka wierszy - pamiętając o spacjach;)
Znaki ucieczki
Odwrócony ukośnik daje nam jeszcze więcej opcji – możemy dzięki niemu używać tak zwanych znaków ucieczki:
Kod | Opis |
\’ | Pojedynczy cudzysłów |
\” | Podwójny cudzysłów |
\\ | Backslash |
\n | Nowa linia – przeskok do następnego wiersza |
\r | Powrót kursora do początku wiersza |
\a | Alert, bell – czyli popularne kiedyś beep wydawane przez komputer. Mój Windows nie reaguje na to. |
\t | Tabulator |
\b | Backspace |
\f | Naleciałość z dawnych lat – wysunięcie kartki w drukarce. To z czasów, kiedy nie było ekranów;) A nowoczesne narzędzia ekranowe różnie mogą to interpretować |
\ooo | Wyświetla znak ASCII pod zadanym kodem ósemkowym (print(„\124”)) |
\xhh | Wyświetla znak ASCII pod zadanym kodem szesnastkowym (print(„\x54”)) |
\uxxxx | Wyświetla znak w UTF-16 |
\Uxxxxxxxx | Wyświetla znak w UTF-32 |
>>> print("Tak\nmożna\nużywać\n\\n")
Tak
można
używać
\n
Tak to mniej więcej wygląda – na pewno pierwsze 5 pozycji się prędzej czy później przyda, reszta niekoniecznie (a przynajmniej nie za szybko, ale warto wiedzieć).
Raw strings – czyli surowe łańcuchy
Przy wyświetlaniu tekstu możemy wymusić ignorowanie znaków ucieczki. W tym celu tuż przed cudzysłowem otwierającym łańcuch wstawiamy r. Sprawdźmy na powyższym przykładzie:
>>> print(r"Tak\nmożna\nużywać\n\\n")
Tak\nmożna\nużywać\n\\n
Wprowadzanie danych z klawiatury
Nie samym printem człowiek żyje – czasami chcemy po prostu zapytać użytkownika o jakieś dane. Z pomocą przychodzi wtedy funkcja input(komunikat) – gdzie komunikat jest opcjonalny – jest to tekst który będzie wyświetlany przed kursorem:
>>> imie = input('Podaj imię: ')
Podaj imię: Zenek
>>> print(imie)
Zenek
Ważna rzecz do zapamiętania – input() zwraca typ str. Jeżeli chcemy wczytać z klawiatury zmienną typu int czy float musimy zastosować konwersję typu (dla przypomnienia – tutaj pisałem o typach danych i konwersji):
# bez konwersji typu
>>> a = input('Podaj liczbę zmiennoprzecinkową: ')
Podaj liczbę zmiennoprzecinkową: 4.5
>>> type(a)
<class 'str'>
# z konwersją typu
>>> a = float(input('Podaj liczbę zmiennoprzecinkową: '))
Podaj liczbę zmiennoprzecinkową: 6.75
>>> type(a)
<class 'float'>
String jako tablica danych
W odróżnieniu od innych podstawowych typów danych string ma jeszcze jedną cechę, o której koniecznie trzeba pamiętać. Jest to zmienna złożona – o ile int czy float zawierały w środku po prostu liczbę, tak string jest tabelą przechowującą zbiór znaków. Możesz ją sobie wyobrazić jako nitkę, na którą nawlekasz koraliki z literkami albo szaszłyk – fachowo znany tez jako typ sekwencyjny. Tablice danych mogą oczywiście zawierać również liczby i obiekty, ale na potrzeby wyjaśnienia jak w ogóle tablice działają string będzie wystarczający. Takie dwie pieczenie na jednym ogniu zrobimy. Ale uwaga – string jest też typem niezmiennym (immutable). Czyli – w raz stworzonej tego typu zmiennej nie możemy na przykład pozamieniać miejscami znaków. Można to zrobić jedynie tworząc nową zmienną pod tą samą nazwą (niszcząc tym samym poprzednią).

Jest to tzw. tablica – czyli każdy koralik (znak) w łańcuchu ma swój numer czyli indeks, przez który możemy się bezpośrednio do niego odwołać. Odwołanie takie ma postać nazwy zmiennej z liczbą w kwadratowych nawiasach, która wskazuje pozycję znaku w tablicy:
>>> napis = "PYTHON"
>>> print(napis)
PYTHON
>>> print(napis[0])
P
>>> print(napis[3])
H
>>> print(napis[5])
N
I nie, nie możemy użyć indeksu wyższego niż długość stringa – 1. Ale za to możemy indeksu wstecznego. Bo tak:)
Zaktualizowana o tę wiedzę rozpiska do poprzedniego przykładu będzie wyglądała tak:

Na niebiesko dorysowałem wsteczne indeksy. Ostatni element łańcucha będzie miał numer -1, a pierwszy będzie wynosił tyle, co ilość znaków w danym łańcuchu (taka zmyłka, bo przy indeksowaniu domyślnym ostatni znak to długość łańcucha – 1). Przykłady użycia:
>>> napis = "PYTHON"
>>> print(napis[-1])
N
>>> print(napis[-3])
H
>>> print(napis[-6])
P
# przekornie spróbujmy wyjść poza zakres
>>> print(napis[-7])
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
print(napis[-7])
IndexError: string index out of range
Sprawdziliśmy przy okazji co się stanie po wyjściu poza zakres – jak widać dostaniemy – na szczęście jasno opisany – błąd: IndexError: string index out of range. Czyli indeks poza zakresem.
String slicing – cięcie łańcuchów
Łańcuch jako typ sekwencyjny może zostać „pocięty” wg zadanego wzorca. Działa to podobnie jak odwoływanie się do poszczególnych indeksów, przy czym w tym przypadku podajemy zakres w kwadratowych nawiasach [po którym znaku ciąć : do którego znaku ciąć]. Jeżeli po jest puste, znaczy tniemy od początku łańcucha. Jeżeli do jest puste – tniemy do końca. Przykłady:
>>> tekst = "testowy tekst do przycięcia"
# jeżeli nie podamy obu parametrów - łańcuch zostanie wyświetlony od początku do końca
>>> tekst[:]
'testowy tekst do przycięcia'
# teraz po 5 znaku do końca
>>> tekst[5:]
'wy tekst do przycięcia'
# a teraz tylko po 2 do 5 znaku
tekst[2:5]
'sto'
# i po 7 znaku do końca
tekst[7:]
' tekst do przycięcia'
Oczywiście działa tutaj też wspomniane wyżej indeksowanie wsteczne:
>>> tekst = "testowy tekst do przycięcia"
>>> tekst[-5:]
'ięcia'
Długość łańcucha znaków
Długość łańcucha znaków możemy odczytać za pomocą funkcji len() – przy czym uwaga – wynikiem jest długość (rozmiar) łańcucha, nie pozycja ostatniego elementu (ten będzie na pozycji długość-1):
>>> napis = "PYTHON"
>>> print(len(napis))
6
Kiedy może nam się to przydać? Przykładowo kiedy chcemy odczytać ostatnią literę wyrazu wprowadzonego przez użytkownika. Nie możemy podać pozycji, bo przecież nie wiemy co użytkownik wpisze. Ale możemy sobie policzyć. Wiemy, że ostatnia literka będzie na pozycji o jeden mniejszej niż długość łańcucha odczytana funkcją len():
>>> napis = input("Podaj napis: ")
Podaj napis: mój napis nieznanej długości
>>> print(len(napis))
28
>>> print(napis[len(napis)-1])
i
Funkcja przyda nam się jeszcze przy wielu innych okazjach.
Inne funkcje i metody przydatne w pracy z tekstem
Poznaliśmy już funkcje str()
oraz len()
. Kolejne, które mogą się przydać, to:
chr()
– konwertuje liczbę całkowitą na znak – ale uwaga – liczba będzie potraktowana jak kod ASCII.
# 32 w kodzie ASCII to spacja
>>> chr(32)
' '
# 67 w kodzie ASCII to litera 'C'
>>> chr(67)
'C'
ord()
– ta funkcja z kolei działa odwrotnie do chr()
– zamienia znak na kod ASCII
# spacja w kodzie ASCII ma numer 32
>>> ord(' ')
32
# litera 'C' w kodzie ASCII ma numer 67
>>> ord('C')
67
count()
– to z kolei metoda (wyjaśnię w następnych odcinkach) – znaczy to mniej więcej tak, że uruchamiamy ją dopisując .count(parametry) do nazwy zmiennej. Count akurat liczy ilość wystąpień tekstu podanego jako parametr:
>>> tekst = 'Król Karol kupił Królowej Karolinie korale koloru koralowego'
# szukamy ile razy w łańcuchu 'tekst' występuje ciąg 'kor'
>>> tekst.count('kor')
2
# a teraz ile razy samo 'ko'
>>> tekst.count('ko')
3
Ale też możemy tej metodzie dodać więcej parametrów – np. początek, indeks od którego znaku ma szukać oraz indeks końcowy. Na przykład:
# sprawdźmy ile razy 'ko' wystąpi od 40 znaku do końca łańcucha
>>> tekst = 'Król Karol kupił Królowej Karolinie korale koloru koralowego'
>>> tekst.count('ko', 40, len(tekst))
2
lower()
i upper()
– jedna zmienia wszystkie litery w łańcuchu na małe, druga na wielkie:
>>> tekst = 'TakITAm TestOWY TekST'
>>> tekst.lower()
'takitam testowy tekst'
>>> tekst.upper()
'TAKITAM TESTOWY TEKST'
Zakończenie (pozorne)
Mamy omówioną całkiem sporą część właściwości i funkcji związanych ze zmiennymi typu string w Pythonie. Na początek wystarczającą, ale jest tego na prawdę dużo więcej i wrócę do tematu w przyszłości. Póki co jednak zapraszam do operatorów oraz instrukcji warunkowych.
Aktualizacje:
2027.07.27 – przykład użycia znaku ucieczki oraz raw strings.