# Strings (Python)

Vysvětlení, jak zacházet s řetězci v jazyce Python a v GTK+.
Sebastian Pölsterl
sebp@k-d-w.org 2011
Marta Maria Casetti
mmcasetti@gmail.com 2012

# Strings

GNOME důrazně doporučuje používat pro psaní aplikací Python 3!

# Řetězce v jazyce Python 2

Python 2 přichází se dvěma různými druhy objektů, které mohou být použity k reprezentaci řetězců – `str` a `unicode`. Instance `unicode` se používají k vyjádření řetězců v Unikódu, zatímco instance typu `str` k bajtové reprezentaci (kódované řetězce). Pod kapotou Python uchovává unikódové řetězce jako 16 nebo 32bitová čísla, v závislosti na tom, jak je zkompilován interpretr jazyka Python.

>>> unicode_string = u"Fu\u00dfb\u00e4lle" >>> print unicode_string Fußbälle

Unikódové řetězce je možné převést na 8bitové řetězce pomocí `unicode.encode()`. 8bitové řetězce v jazyce Python mají metodu `str.decode()`, které interpretuje řetězec pomocí zadaného kódování (tj. opak metody `unicode.encode()`):

>>> type(unicode_string) <type 'unicode'> >>> unicode_string.encode("utf-8") 'Fu\xc3\x9fb\xc3\xa4lle' >>> utf8_string = unicode_string.encode("utf-8") >>> type(utf8_string) <type 'str'> >>> unicode_string == utf8_string.decode("utf-8") True

Bohužel, Python 2.x umožňuje míchat typy `unicode` a `str`, v případě, že 8bitový řetězec obsahuje jen 7bitové hodnoty (ASCII), ale když obsahuje jiné hodnoty (ne ASCII), obdržíte chybu UnicodeDecodeError.

# Řetězce v jazyce Python 3

Od verze Python 3.0 jsou všechny řetězce uchovávány jako Unikód v instanci typu `str`. Kódované řetězce jsou na druhou stranu reprezentovány jako binární data ve formě instance typu `bytes`. Koncepčně `str` představuje řetězec, zatímco `bytes` data. K přechodu ze `str` na `bytes` použijte `encode()` a pro přechod z `bytes` na `str` zase `decode()`.

Navíc již nadále není možné míchat unikódové řetězce s kódovanými řetězci, protože to způsobí chybu `TypeError`:

>>> text = "Fu\u00dfb\u00e4lle" >>> data = b" sind rund" >>> text + data Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't convert 'bytes' object to str implicitly >>> text + data.decode("utf-8") 'Fußbälle sind rund' >>> text.encode("utf-8") + data b'Fu\xc3\x9fb\xc3\xa4lle sind rund'

# Unikód v GTK+

GTK+ používá pro veškerý text řetězce kódované v UTF-8. To znamená, že když zavoláte metodu vracející řetězec, vždy obdržíte instanci typu `str`. To stejné platí pro metody, které očekávají jeden nebo více řetězců jako parametr, musí být kódované v UTF-8. Nicméně, kvůli pohodlí objekt `PyGObject` automaticky převádí instance `unicode` na `str`, když jsou předány jako argument:

>>> from gi.repository import Gtk >>> label = Gtk.Label() >>> unicode_string = u"Fu\u00dfb\u00e4lle" >>> label.set_text(unicode_string) >>> txt = label.get_text() >>> type(txt) <type 'str'>

Navíc:

>>> txt == unicode_string

by vrátilo `False` s varováním `__main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal` (`Gtk.Label.get_text()` vždy vrátí instanci `str`, a proto si `txt` a `unicode_string` nejsou rovny).

Toto je obzvláště důležité, kdy chcete svůj program internacionalizovat pomocí `gettext`. Musíte zajistit, že `gettext` bude vracet pro všechny jazyky 8bitové řetězce kódované v UTF-8.

Obecně je doporučováno v aplikacích GTK+ vůbec nepoužívat objekty `unicode` a používat jen objekty `str` kódované v UTF-8, protože GTK+ nemá objekty `unicode` plně integrovány.

Kódování řetězců je více konzistentní ve verzi Python 3.x, protože `PyGObject` automaticky kóduje/dekóduje do/z UTF-8, když předáváte řetězec metodě, nebo metoda vrací řetězec. Řetězce nebo texty budou vždy reprezentovány jen jako instance `str`.

# Odkazy

Jak zacházet s řetězci – Výuka jazyka Python s GTK+ 3