Kurzusok
/
Python
Python
/
Tanterv
/
Stringformázás
St

Stringformázás ebben a kurzusban: Python

1 feladat

A(z) Stringformázás fogalomról

String formázás Pythonban

A string formázás során értékeket alakítunk stringgé, majd beillesztjük őket egy string-sablonba. A Python zenéje szerint „egy nyilvánvaló módja van annak, hogy valamit megvalósítsunk Pythonban”. De ami a string formázást illeti, a dolgok egy kicsit... kevésbé zenek.

Meglepő lehet, hogy négy fő módja van a string formázásnak Pythonban, mindegyik más-más helyzetre. Ennek egy része Python hosszú történetéből fakad, más része pedig olyan szempontokból, mint a nemzetköziesítés vagy a bemenet tisztítása. A string formázás eszköztárának legújabb darabjaival kezdünk, és visszafelé haladva jutunk el a „régi stílusú”, azaz „printf() stílusú” string formázásig.

Literál string interpoláció: az f-string

A Python 3.6-ban bevezetett f-string-ek (a „formatted strings”, azaz formázott stringek rövidítése) vagy a literál string interpoláció segítségével gyorsan és hatékonyan kiértékelhetünk (és formázhatunk) kifejezéseket és stringeket str típussá úgy, hogy az idézőjelek elé írjuk az f (vagy F) előtagot (például így: f'{object}').

Az f-string-ek mindenféle lezáró stringtípussal használhatók, például egysoros (' vagy ") és többsoros (''' vagy """) stringekkel. A {} belsejébe írt változókat, kifejezéseket vagy más típusokat először kiértékeli, majd str típussá alakítja, végül összefűzi a kapcsos zárójeleken kívüli str-ekkel.

Ebben a példában két változó értékét illesztjük be egy mondatba (egy str és egy 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.'

A kiértékelt kifejezések szinte bármik lehetnek. Néhány a kiértékelhető lehetőségek (széles skálájából): str-ek, számok, változók, aritmetikai kifejezések, feltételes kifejezések, beépített típusok, szeletek, függvények, lambdák, komprehenziók, vagy bármilyen objektum, amelynél definiálva van a __str__ vagy a __repr__ metódus.

Az egyszerűtől a bonyolult felé haladva:

Változó beillesztése: az f-string legegyszerűbb használata, hogy egy változót közvetlenül a stringbe írunk.

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

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

Kifejezések a {} belsejében: a kapcsos zárójelek között bármilyen érvényes Python-kifejezés kiértékelhető. Figyeld meg, hogy ha egy szimpla idézőjeles f-string-en belül dupla idézőjelet használsz (vagy fordítva), elkerülheted az escape-szekvenciákat:

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

Kimenet formázása: a formátumspecifikációs mini-nyelvvel szabályozhatod az igazítást, a numerikus pontosságot és még sok mást. A formátumspecifikáció az érték után következik, tőle egy : választja el.

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

Így áll mindez össze: változók, kifejezések, függvényhívások és kimenetformázás:

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

Két fő korlátot érdemes szem előtt tartani. Az f-string-kifejezések nem lehetnek üresek. Ráadásul a Python 3.12 előtt nem tartalmazhattak megjegyzéseket.

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

A string interpoláció nem használható együtt a GNU gettext API-val a nemzetköziesítéshez (I18N) és a lokalizációhoz (L10N), ezért minden „szöveg stringbe csomagolását” érintő fordítói helyzetben azt javasoljuk, hogy f-string helyett az alább ismertetett string.Template osztályt vagy a str.format() metódust használd.

Arra is gondolj, hogy a f-string zárójelein ({}) belüli kifejezések használata hasonló az eval() vagy az exec() használatához, ezért nem túl biztonságos, és soha nem szabad felhasználói bemenettel használni.

A str.format() metódus

A str.format() metódus a stringen belüli helyőrzőket cseréli le a függvénynek átadott argumentumokra. A helyőrzőket név ({price}), szám ({0} vagy indexek), vagy akár üres (pozíciós) helyőrző ({}) jelöli.

Például:

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

Az f-string-ekhez hasonlóan a Python str.format() metódusa is támogatja a mini-nyelv formátumspecifikációinak széles skáláját, amelyekkel igazíthatsz szöveget, csonkíthatsz tizedes törteket és még sok mást.

A teljes formátumspecifikációs minta {[<name>][!<conversion>][:<format_specifier>]}:

  • A <name> lehet névvel ellátott helyőrző, szám vagy üres.
  • A !<conversion> elhagyható, és a három konverzió egyike kell legyen: !s a str() konverzióhoz, !r a repr() konverzióhoz vagy !a az ascii() konverzióhoz. Alapértelmezés szerint a str() konverziót használja.
  • A :<format_specifier> elhagyható, és azt szabályozza, hogyan jelenjen meg az érték. A lehetséges beállításokról itt találsz bővebb információt.

Példa a konverziókra egy ékezetes betű esetén:

# 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ë'."

Példák gyakori formátumspecifikációkra:

# 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

További példák e dokumentáció végén találhatók.

% formázás, avagy printf() stílusú formázás

A % operátor formázásra való használata a legrégebbi stringformázási módszer Pythonban. A C nyelvből származik, és lehetővé teszi pozíciós argumentumok használatát egy str összeállításához.

Ezt a módszert felváltotta az f-string és a str.format(), ezért kapta a % formázás a „Old Style”, azaz „régi stílus” becenevet. Még mindig találkozhatsz vele Python 2-es és/vagy örökölt kódban. Bár ez a módszer Python 3.x-ben is működik, a % formázást általában kerülik, mert hajlamos a hibákra, kevésbé hatékony, kevesebb beállítást kínál, és a helyőrző és az argumentum bármilyen eltérése kivételt válthat ki. A % operátor használata hasonlít a printf() függvényéhez, ezért néha printf formázásnak is nevezik.

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

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

A fenti példában a % operátor futásidőben a %s helyőrzőt a name változóra cseréli. Ha több változót szeretnél hozzáadni egy stringhez, a % után egy tuple-t kell megadnod, amelyben minden helyőrzőhöz egy objektum tartozik:

# 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-sablonok

A string.Template() (nem tévesztendő össze a Python 3.14 t-strings funkciójával) a string modul egyik osztálya (szemben a beépített str típussal), amely a Python szabványos könyvtárának része, de a használatához importálni kell. A string-sablonok $-alapú helyettesítést támogatnak, és sokkal egyszerűbbek, kevesebbre képesek, mint az itt említett többi lehetőség. Ugyanakkor nagyon hasznosak lehetnek bonyolult nemzetköziesítési feladatokhoz vagy külső bemenetek tisztításához.

A string.Template biztonságosabbnak számít nem megbízható felhasználói bemenet esetén, mert megakadályozza tetszőleges kifejezések kiértékelését és az objektumattribútumok elérését, ami mérsékli a formátumstring-injektálásos támadásokat.

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

A string.Template-ről több információt a Python dokumentációjában találsz.

Hogyan válaszd ki, melyik formázási módszert használd?

Ennyi lehetőség és mini-nyelv közepette hogyan döntsd el, mihez nyúlj, amikor Python stringeket formázol? Íme néhány gyors irányelv:

  1. Az f-string-ek a legújabbak és a legkönnyebben olvashatók. Ha nincs szükséged nemzetköziesítésre, Python 3.6+ esetén ezt érdemes előnyben részesíteni.

  2. A str.format() sokoldalú, hatékony, és kompatibilis a gnu gettext-tel meg a Python legtöbb verziójával.

  3. Ha az egyszerűségre, a biztonságra és/vagy a nagy volumenű nemzetköziesítésre van szükséged, a string.Template() segíthet csökkenteni a kockázatokat, amikor felhasználói bemeneteket kell kezelni, és fordítási stringek körítésére is használható.

  4. A % operátort új kódban általában elavultnak tartják, bár a modern Pythonban még működik. Leginkább régebbi kódbázisokkal való kompatibilitás miatt érdemes használni. A % formázás hajlamosabb a hibákra (és kevesebb funkciót kínál), mint a többi módszer, ráadásul gondot okozhat a nem ASCII karakterek megjelenítésében. Ha használni szeretnéd, nézd meg a konkrét Python-disztribúciódat a támogatási részletekért.

Ha tovább szeretnél menni, az all about formatting és a Python String Formatting Best Practices jó kiindulópontok.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg