Διαδρομές
/
Python
Python
/
Ύλη
/
Μορφοποίηση συμβολοσειρών
Μο

Μορφοποίηση συμβολοσειρών σε Python

1 άσκηση

Σχετικά με την έννοια Μορφοποίηση συμβολοσειρών

Μορφοποίηση συμβολοσειρών στην Python

Η μορφοποίηση συμβολοσειρών είναι η διαδικασία μετατροπής τιμών σε συμβολοσειρές και η εισαγωγή τους σε ένα πρότυπο συμβολοσειράς. Το Zen of Python υποστηρίζει ότι θα πρέπει να υπάρχει "ένας προφανής τρόπος να κάνεις κάτι στην Python". Αλλά όταν πρόκειται για τη μορφοποίηση συμβολοσειρών, τα πράγματα είναι λίγο... λιγότερο zen.

Μπορεί να σου φανεί περίεργο να ανακαλύψεις ότι υπάρχουν τέσσερις κύριοι τρόποι να κάνεις μορφοποίηση συμβολοσειρών στην Python, καθένας για διαφορετικό σενάριο. Ένα μέρος αυτού οφείλεται στη μακρά ιστορία της Python και ένα μέρος σε ζητήματα όπως η διεθνοποίηση ή η εξυγίανση της εισόδου. Θα ξεκινήσουμε με τις πιο πρόσφατες προσθήκες στην εργαλειοθήκη μορφοποίησης συμβολοσειρών και θα προχωρήσουμε προς τα πίσω, στο "παλιό στυλ" ή στο στυλ μορφοποίησης "printf()".

Παρεμβολή συμβολοσειράς: Το f-string

Εισήχθησαν στην Python 3.6 και τα f-strings (συντομογραφία του "formatted strings"), δηλαδή η παρεμβολή συμβολοσειράς, είναι ένας τρόπος να αξιολογείς (και να μορφοποιείς) γρήγορα και αποδοτικά εκφράσεις και συμβολοσειρές σε τύπο str χρησιμοποιώντας το πρόθεμα f (ή F) πριν από τα εισαγωγικά (έτσι: f'{object}').

Τα f-strings μπορούν να χρησιμοποιηθούν με όλους τους τύπους περικλεισμένων συμβολοσειρών, όπως μονής γραμμής (' ή ") και πολλαπλών γραμμών (''' ή """). Οποιεσδήποτε μεταβλητές, εκφράσεις ή άλλοι τύποι τοποθετούνται μέσα στα {} αξιολογούνται πρώτα, μετά μετατρέπονται σε str και τελικά συνενώνονται με οποιαδήποτε str έξω από τα άγκιστρα.

Σε αυτό το παράδειγμα, εισάγουμε δύο τιμές μεταβλητών σε μια πρόταση (μία str και μία float):

>>> name = 'eighth'
>>> value = 1/8

# The f-string, using the two values.
# The .2f format code truncates, so the value displays as 0.12.
>>> f'An {name} is approximately {value:.2f}.'
'An eighth is approximately 0.12.'

Οι εκφράσεις που αξιολογούνται μπορούν να είναι σχεδόν οτιδήποτε. Μερικές από τις (μεγάλες) δυνατότητες που μπορούν να αξιολογηθούν: strs, αριθμοί, μεταβλητές, αριθμητικές εκφράσεις, εκφράσεις υπό συνθήκη, ενσωματωμένοι τύποι, slices, συναρτήσεις, lambdas, comprehensions ή οποιαδήποτε αντικείμενα με ορισμένες μεθόδους __str__ ή __repr__.

Προχωρώντας από τα απλά στα σύνθετα:

Εισαγωγή μεταβλητής: η απλούστερη χρήση ενός f-string είναι να τοποθετήσεις μια μεταβλητή απευθείας μέσα στη συμβολοσειρά.

# Assigning a variable.
>>> name = "World"

# Inserting that variable.
>>> f'Hello, {name}!'
'Hello, World!'

Εκφράσεις μέσα στα {}: οποιαδήποτε έγκυρη έκφραση της Python μπορεί να αξιολογηθεί μέσα στα άγκιστρα. Σημείωσε ότι η χρήση διπλών εισαγωγικών μέσα σε ένα f-string με μονά εισαγωγικά (ή το αντίστροφο) αποφεύγει την ανάγκη για ακολουθίες διαφυγής:

# A dictionary of key:value pairs.
>>> waves = {'water': 1, 'light': 3, 'sound': 5}

# Inserting the whole dict.
>>> f'Wave ranks: {waves}'
"Wave ranks: {'water': 1, 'light': 3, 'sound': 5}"

# An expression can be evaluated inline:
>>> f"Tenfold the value of 'light' is {waves['light'] * 10}."
"Tenfold the value of 'light' is 30."

# A method call can also be evaluated inline:
>>> f'{"hello world!".title()} is a classic greeting.'
'Hello World! is a classic greeting.'

# An f-string can be nested inside another f-string:
>>> f"{f'hello world!'.title()} is a classic greeting."
'Hello World! is a classic greeting.'

Μορφοποίηση εξόδου: η μίνι-γλώσσα προδιαγραφών μορφής μπορεί να χρησιμοποιηθεί για να ελέγχεις τη στοίχιση, την αριθμητική ακρίβεια και πολλά άλλα. Η προδιαγραφή μορφής πηγαίνει μετά την τιμή, χωρισμένη με :.

# Right-align a value to ten characters, and round it to 3 decimal places.
>>> value = 1 / 7
>>> f'One seventh is {value:10.3f}.'
'One seventh is      0.143.'

# A format specification can be set using variables as well.
>>> padding = 10
>>> precision = 3
>>> f'One seventh is {value:{padding}.{precision}f}.'
'One seventh is      0.143.'

Βάζοντάς τα όλα μαζί: μεταβλητές, εκφράσεις, κλήσεις συναρτήσεων και μορφοποίηση εξόδου:

>>> precision = 3
>>> f"{30e8 * 111_000:6.{precision}e}"
'3.330e+14'

>>> verb = 'meet'
>>> the_end = ['end', 'of', 'transmission']
>>> f'"Have a {"NICE".lower()} day, I will {verb} you after {30e8 * 111_000:6.{precision}e} light-years."{the_end}'
'"Have a nice day, I will meet you after 3.330e+14 light-years."[\'end\', \'of\', \'transmission\']'

# Did you notice the escaped single-quotes in the previous example?
# Using double quotes instead of single quotes for the f-string means the list's single-quoted strings print cleanly.
>>> f"Have a nice day. {the_end}"
"Have a nice day. ['end', 'of', 'transmission']"

Υπάρχουν δύο κύριοι περιορισμοί που πρέπει να έχεις υπόψη. Οι εκφράσεις των f-string δεν μπορούν να είναι κενές. Επιπλέον, πριν από την Python 3.12, δεν μπορούσαν να περιέχουν σχόλια.

>>> f"An empty expression will error: {}"
SyntaxError: f-string: empty expression not allowed

>>> word = 'word'
>>> f"""A comment in a triple quoted f-string: {
    word # I chose a nice variable
}"""
'A comment in a triple quoted f-string: word'
Caution

Η παρεμβολή συμβολοσειράς δεν μπορεί να χρησιμοποιηθεί μαζί με το GNU gettext API για διεθνοποίηση (I18N) και τοπικοποίηση (L10N), οπότε συνιστάται να χρησιμοποιείς την κλάση string.Template ή τη μέθοδο str.format() που περιγράφεται παρακάτω αντί για ένα f-string σε οποιοδήποτε σενάριο μετάφρασης "περιτύλιξης συμβολοσειρών".

Έχε επίσης υπόψη ότι η χρήση εκφράσεων μέσα στα άγκιστρα {} του f-string είναι παρόμοια με τη χρήση των eval() ή exec(), οπότε δεν είναι πολύ ασφαλής και δεν θα πρέπει να χρησιμοποιείται ποτέ με είσοδο από τον χρήστη.

Η μέθοδος str.format()

Η μέθοδος str.format() αντικαθιστά τους placeholders μέσα στη συμβολοσειρά με τιμές που δίνονται ως ορίσματα στη συνάρτηση. Οι placeholders προσδιορίζονται με ονόματα ({price}), αριθμούς ({0} ή θέσεις) ή ακόμα και κενούς (θεσιακούς) placeholders {}.

Για παράδειγμα:

# A named placeholder and a positional placeholder.
>>> 'My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder')
'My text: named placeholder and 12.'

Όπως και με τα f-strings, η str.format() της Python υποστηρίζει μια ολόκληρη γκάμα από προσδιοριστές μορφής της μίνι-γλώσσας που μπορούν να χρησιμοποιηθούν για στοίχιση κειμένου, περικοπή δεκαδικών αριθμών και άλλα.

Το πλήρες μοτίβο προσδιοριστή μορφοποίησης είναι {[<name>][!<conversion>][:<format_specifier>]}:

  • Το <name> μπορεί να είναι ένας placeholder με όνομα, ένας αριθμός ή κενό.
  • Το !<conversion> είναι προαιρετικό και θα πρέπει να είναι μία από αυτές τις τρεις μετατροπές: !s για τη str(), !r για τη repr() ή !a για τη ascii(). Από προεπιλογή, χρησιμοποιείται η str().
  • Το :<format_specifier> είναι προαιρετικό και ελέγχει πώς εμφανίζεται η τιμή. Περισσότερες πληροφορίες για τις διαθέσιμες επιλογές μπορείς να βρεις εδώ.

Παράδειγμα μετατροπών για ένα γράμμα με διακριτικό:

# Fills in the object at index zero, converted to a string.
>>> 'An e with an umlaut: {0!s}'.format('ë')
'An e with an umlaut: ë'


# Fills in the object at index zero, converted to a repr.
>>> 'An e with an umlaut (object representation): {0!r}'.format('ë')
"An e with an umlaut (object representation): 'ë'"


# Fills in the object at index zero, converted to ASCII.
>>> 'An e with an umlaut converted into ASCII: {0!a}'.format('ë')
"An e with an umlaut converted into ASCII: '\xeb'"


# Fills in the object in the first position,
# then fills in the object in the second position formatted as a repr.
>>> 'She said her name is not {} but {!r}.'.format('Chloe', 'Zoë')
"She said her name is not Chloe but 'Zoë'."

Παραδείγματα κοινών προσδιοριστών μορφής:

# Integer and binary/hex representations of the same number.
>>> my_num = 42
>>> f"{my_num} in binary is {my_num:b}. In hex, it is {my_num:x}"
"42 in binary is 101010. In hex, it is 2a"

# Alignment: left (<), right (>), and center (^) using up to ten characters total.
>>> f"[{"left":<10}] [{"right":>10}] [{"center":^10}]"
"[left      ] [     right] [  center  ]"

# Float precision and scientific notation (up to three decimal places).
>>> pi = 3.141592653589793
>>> f"Fixed: {pi:.3}  Scientific: {pi:.3e}"
"Fixed: 3.142  Scientific: 3.142e+00"

# Thousands separator and percentage.
>>> balance = 1000
>>> rate = 0.0225
>>> f"Balance: ${balance:,.0f}  Interest rate: {rate:.1%}"
"Balance: $1,000  Interest rate: 2.2%"

# Putting it all together:
>>> items = [("Widget", 1250, 9.991), ("Gadget", 37, 24.503), ("Doohickey", 4, 149.002)]
>>> header = f"{"Item":<12} {"Qty":>6} {"Price":>9}"
>>> print(header)
Item            Qty     Price
>>> for name, qty, price in items:
...     print(f"{name:<12} {qty:>6} {price:>9.2f}")
Widget         1250      9.99
Gadget           37     24.50
Doohickey         4    149.00

Περισσότερα παραδείγματα εμφανίζονται στο τέλος αυτής της τεκμηρίωσης.

Μορφοποίηση με % ή μορφοποίηση στυλ printf()

Η χρήση του τελεστή % για μορφοποίηση είναι η παλαιότερη μέθοδος μορφοποίησης συμβολοσειρών στην Python. Προέρχεται από τη γλώσσα C και επιτρέπει τη χρήση θεσιακών ορισμάτων για τη δημιουργία μιας str.

Αυτή η μέθοδος έχει αντικατασταθεί και από τα f-strings και από τη str.format(), γι' αυτό το παρατσούκλι της μορφοποίησης με % είναι "Old Style". Μπορεί ακόμα να βρεθεί στην Python 2 ή/και σε παλιό κώδικα. Αν και η χρήση αυτής της μεθόδου λειτουργεί στην Python 3.x, η μορφοποίηση με % συνήθως αποφεύγεται επειδή μπορεί να είναι επιρρεπής σε λάθη, είναι λιγότερο αποδοτική, έχει λιγότερες διαθέσιμες επιλογές και οποιαδήποτε αναντιστοιχία μεταξύ placeholder και ορίσματος μπορεί να πετάξει μια εξαίρεση. Η χρήση του τελεστή % είναι παρόμοια με τη printf(), γι' αυτό μερικές φορές ονομάζεται και μορφοποίηση printf.

# Assigning a variable.
>>> name = "Anna-conda"

# Building a string using %.
>>> "The snake's name is %s." % name
"The snake's name is Anna-conda."

Στο παραπάνω παράδειγμα, ο τελεστής % αντικαθιστά τον placeholder %s με τη μεταβλητή name κατά την εκτέλεση. Αν θέλεις να προσθέσεις πολλαπλές μεταβλητές σε μια συμβολοσειρά, πρέπει να δώσεις μια πλειάδα που να περιέχει ένα αντικείμενο για κάθε placeholder μετά το %:

# Assigning variables.
>>> name = "Billy the Kid"
>>> fruit = "grapes"

# Building a string using %.
>>> "Surprisingly, %s's favorite snack was %s." %(name, fruit)
"Surprisingly, Billy the Kid's favorite snack was grapes."

Συμβολοσειρές προτύπων

Η string.Template() (μην τη συγχέεις με τα t-strings της Python 3.14) είναι μια κλάση από το module string (σε αντίθεση με τον ενσωματωμένο τύπο str), η οποία αποτελεί μέρος της βασικής βιβλιοθήκης της Python, αλλά πρέπει να εισαχθεί για να χρησιμοποιηθεί. Οι συμβολοσειρές προτύπων υποστηρίζουν υποκατάσταση με $ και είναι πολύ πιο απλές και λιγότερο ικανές από τις άλλες επιλογές που αναφέρονται εδώ. Ωστόσο, μπορούν να είναι πολύ χρήσιμες για περίπλοκη διεθνοποίηση ή για την εξυγίανση εξωτερικών δεδομένων εισόδου.

Η string.Template θεωρείται ασφαλέστερη για μη αξιόπιστη είσοδο χρήστη, επειδή αποτρέπει την αξιολόγηση αυθαίρετων εκφράσεων ή την πρόσβαση σε χαρακτηριστικά αντικειμένων, γεγονός που μετριάζει τις επιθέσεις έγχυσης μέσω συμβολοσειρών μορφοποίησης.

>>> from string import Template

>>> name = "Anna-Conda"

# Creating a Template with placeholder text.
>>> template_string = Template("The snake called `$snake_name` has escaped!")

# Calling .substitute() to replace the placeholder with a value.
>>> template_string.substitute(snake_name=name)
'The snake called `Anna-Conda` has escaped!'

Περισσότερες πληροφορίες για τη string.Template μπορείς να βρεις στην τεκμηρίωση της Python.

Πώς επιλέγεις ποια μέθοδο μορφοποίησης να χρησιμοποιήσεις;

Με όλες αυτές τις επιλογές και τις μίνι-γλώσσες, πώς αποφασίζεις τι να χρησιμοποιήσεις όταν μορφοποιείς συμβολοσειρές στην Python; Ορίστε μερικές γρήγορες οδηγίες:

  1. Τα f-strings είναι τα νεότερα και τα πιο ευανάγνωστα. Αν δεν χρειάζεται να κάνεις διεθνοποίηση, θα πρέπει να είναι η προτιμώμενη μέθοδος για Python 3.6+.

  2. Η str.format() είναι ευέλικτη, ισχυρή και συμβατή και με το gnu gettext και με τις περισσότερες εκδόσεις της Python.

  3. Αν αυτό που χρειάζεσαι είναι απλότητα, ασφάλεια ή/και έντονη διεθνοποίηση, η string.Template() μπορεί να χρησιμοποιηθεί για να μετριάσεις τους κινδύνους όταν πρέπει να χειριστείς εισόδους από χρήστες, και για την περιτύλιξη συμβολοσειρών μετάφρασης.

  4. Ο τελεστής % θεωρείται γενικά παρωχημένος για νέο κώδικα, αν και εξακολουθεί να λειτουργεί στη σύγχρονη Python. Θα πρέπει κυρίως να χρησιμοποιείται για συμβατότητα με παλαιότερα codebases. Η μορφοποίηση με % είναι πιο επιρρεπής σε λάθη (και έχει λιγότερες λειτουργίες) από τις άλλες μεθόδους, και μπορεί να οδηγήσει σε προβλήματα με την εμφάνιση χαρακτήρων που δεν είναι ASCII. Έλεγξε τη συγκεκριμένη διανομή της Python που χρησιμοποιείς για λεπτομέρειες υποστήριξης, αν σκοπεύεις να τη χρησιμοποιήσεις.

Αν θέλεις να προχωρήσεις παραπέρα, τα τα πάντα για τη μορφοποίηση και Βέλτιστες πρακτικές μορφοποίησης συμβολοσειρών στην Python είναι καλά σημεία για να ξεκινήσεις.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα