# Συμβολοσειρές (Python)

Μια εξήγηση πώς να αντιμετωπίσετε τις συμβολοσειρές σε Python και GTK+.
Sebastian Pölsterl
sebp@k-d-w.org 2011
Marta Maria Casetti
mmcasetti@gmail.com 2012

# Συμβολοσειρές

# Ορισμοί

Εννοιολογικά μια συμβολοσειρά είναι μια λίστα χαρακτήρων όπως 'A', 'B', 'C' or 'È'. Οι χαρακτήρες είναι αφηρημένες αναπαραστάσεις και το νόημα τους εξαρτάται από τη γλώσσα και το περιεχόμενο στο οποίο χρησιμοποιούνται. Το τυπικό Unicode περιγράφει πώς οι χαρακτήρες αναπαριστώνται από σημεία κώδικα. Για παράδειγμα οι παραπάνω χαρακτήρες αναπαριστώνται με τα σημεία κώδικα U+0041, U+0042, U+0043 και U+00C9, αντίστοιχα. Βασικά, τα σημεία κώδικα είναι αριθμοί στην περιοχή από 0 έως 0x10FFFF.

Η αναπαράσταση μιας συμβολοσειράς ως μιας λίστας σημείων κώδικα είναι αφηρημένη. Για να μετατρέψετε αυτήν την αφηρημένη αναπαράσταση σε μια σειρά bytes η συμβολοσειρά Unicode πρέπει να κωδικοποιηθεί. Η απλούστερη μορφή κωδικοποίησης είναι η ASCII και εκτελείται ως εξής:

Εάν το σημείο κώδικα είναι αυστηρά μικρότερο από 128, κάθε byte είναι η ίδια όπως η τιμή του σημείου κώδικα.

Εάν το σημείο κώδικα είναι 128 ή μεγαλύτερο, η συμβολοσειρά Unicode δεν μπορεί να αναπαρασταθεί σε αυτήν την κωδικοποίηση. (Ο Python εγείρει μια εξαίρεση UnicodeEncodeError σε αυτήν την περίπτωση.)

Αν και η κωδικοποίηση ASCII είναι απλή στην εφαρμογή μπορεί να κωδικοποιήσει μόνο 128 διαφορετικούς χαρακτήρες που είναι ανεπαρκείς. Μια από τις συνηθέστερες χρησιμοποιούμενες κωδικοποιήσεις που αντιμετωπίζει αυτό το πρόβλημα είναι η UTF-8 (μπορεί να χειριστεί οποιοδήποτε σημείο κώδικα Unicode). UTF σημαίνει “μορφή μετασχηματισμού κοινού κώδικα”, και το ‘8’ σημαίνει ότι αριθμοί 8 δυαδικών χρησιμοποιούνται στην κωδικοποίηση.

# Συμβολοσειρές σε Python 2

Ο Python 2 έρχεται με δύο διαφορετικά είδη αντικειμένων που μπορούν να χρησιμοποιηθούν για αναπαράσταση συμβολοσειρών, `str` και `unicode`. Περιπτώσεις του `unicode` χρησιμοποιούνται για να εκφράσουν συμβολοσειρές Unicode, ενώ περιπτώσεις του τύπου `str` είναι αναπαραστάσεις byte (η κωδικοποιημένη συμβολοσειρά). Στα αφανή, ο Python αντιπροσωπεύει συμβολοσειρές Unicode ως είτε 16- ή 32- δυαδικών ακέραιους, ανάλογα με το πώς ο διερμηνευτής Python μεταγλωττίστηκε.

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

Οι συμβολοσειρές Unicode μπορούν να μετατραπούν σε συμβολοσειρές 8 δυαδικών με `unicode.encode()`. Οι συμβολοσειρές 8 δυαδικών έχουν μια μέθοδο `str.decode()` που ερμηνεύει τη συμβολοσειρά χρησιμοποιώντας τη δεδομένη κωδικοποίηση (δηλαδή, είναι το αντίστροφο της `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

Δυστυχώς, ο Python 2.x επιτρέπει την ανάμειξη `unicode` και `str` εάν η συμβολοσειρά 8 δυαδικών συμβεί να περιέχει μόνο bytes μόνο 7 δυαδικών (ASCII), αλλά θα μπορούσε να πάρει UnicodeDecodeError εάν περιέχει μη ASCII τιμές.

# Συμβολοσειρές σε Python 3

Από τον Python 3.0, όλες οι συμβολοσειρές αποθηκεύονται ως Unicode σε ένα στιγμιότυπο του τύπου `str`. Κωδικοποιημένες συμβολοσειρές από την άλλη μεριά αναπαριστώνται ως δυαδικά δεδομένα στη φόρμα στιγμιοτύπων του τύπου bytes. Εννοιολογικά, ο `str` αναφέρεται σε κείμενο, ενώ τα bytes αναφέρονται σε δεδομένα. Χρησιμοποιήστε `encode()` για μετάβαση από `str` σε `bytes` και `decode()` για μετάβαση από `bytes` σε `str`.

Επιπλέον, δεν είναι πια δυνατό να αναμείξετε συμβολοσειρές Unicode με κωδικοποιημένες συμβολοσειρές, επειδή θα καταλήξει σε ένα `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'

# Unicode σε GTK+

Το GTK+ χρησιμοποιεί κωδικοποιημένες συμβολοσειρές UTF-8 για όλα τα κείμενα. Αυτό σημαίνει ότι εάν καλέσετε μια μέθοδο που επιστρέφει μια συμβολοσειρά θα παίρνετε πάντα ένα στιγμιότυπο του τύπου `str`. Το ίδιο εφαρμόζεται στις μεθόδους που περιμένουν μια ή περισσότερες συμβολοσειρές ως παράμετρο, πρέπει να είναι κωδικοποιημένες UTF-8. Όμως, για ευκολία το PyGObject θα μετατρέπει αυτόματα οποιοδήποτε στιγμιότυπο unicode σε str εάν του δοθεί ως όρισμα:

>>> 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'>

Επιπλέον:

>>> txt == unicode_string

Θα επέστρεφε `False`, με την προειδοποίηση `__main__:1: UnicodeWarning: η σύγκριση όμοιων Unicode απέτυχε να μετατρέψει και τα δυο ορίσματα σε Unicode - ερμηνεύοντας τα ως ανόμοια` (`Gtk.Label.get_text()` θα επιστρέφει πάντα ένα στιγμιότυπο `str`· συνεπώς, `txt` and `unicode_string` δεν είναι όμοια).

Αυτό είναι ιδιαίτερα σημαντικό εάν θέλετε να διεθνοποιήσετε το πρόγραμμά σας χρησιμοποιώντας `gettext`. Πρέπει να βεβαιωθείτε ότι η `gettext` θα επιστρέψει κωδικοποιημένες συμβολοσειρές 8 δυαδικών UTF-8 για όλες τις γλώσσες.

Γενικά συνιστάται να μην χρησιμοποιείτε αντικείμενα `unicode` σε εφαρμογές GTK+ καθόλου και να χρησιμοποιείτε κωδικοποιημένα αντικείμενα `str` UTF-8 αφού το GTK+ δεν ενσωματώνει πλήρως αντικείμενα `unicode`.

Με τον Python 3.x τα πράγματα είναι πολύ πιο ομοιόμορφα, επειδή το PyGObject θα κωδικοποιήσει/αποκωδικοποιήσει αυτόματα προς/από UTF-8 εάν περάσετε μια συμβολοσειρά σε μια μέθοδο ή εάν μια μέθοδος επιστρέφει μια συμβολοσειρά. Συμβολοσειρές, ή κείμενο, θα αναπαριστώνται πάντα ως περιπτώσεις μόνο `str`:

# Αναφορές

Πώς να αντιμετωπίσετε τις συμβολοσειρές - Το μάθημα Python GTK+ 3