Itt vagy: Kezdőlap ‣ Ugorj fejest a Python 3-ba ‣
Nehézségi szint: ♦♦♦♢♢
❝ Azért mondom, mert az egyik barátom vagy.
Az én ábécém ott kezdődik, ahol a tiéd véget ér! ❞
– Dr. Seuss, On Beyond Zebra!
Kevesen gondolnak bele, de a szöveg hihetetlenül bonyolult. Kezdjük az ábécével. Bougainville lakosai rendelkeznek a világ legrövidebb ábécéjével, az ő Rotokas ábécéjük csak 12 betűből áll: A, E, G, I, K, O, P, R, S, T, U és V. A spektrum másik végén a kínai, japán, és koreai nyelvek állnak, több ezer karakterrel. Az angol természetesen 26 betűt tartalmaz – 52-t, ha a kis- és nagybetűket külön számolod – , valamint néhány !@#$%& írásjelet.
Amikor „szövegről” beszélsz, akkor valószínűleg „a számítógéped képernyőjén megjelenő karakterekre és szimbólumokra” gondolsz. De a számítógépek nem karaktereket és szimbólumokat kezelnek, hanem biteket és bájtokat. Minden szöveg, amit valaha a számítógép képernyőjén láttál, valójában egy adott karakterkódolásban van tárolva. Nagy vonalakban a karakterkódolás biztosítja a leképezést a képernyőn látható és a számítógép által a memóriában és lemezen tárolt dolgok között. Számos különböző karakterkódolás létezik, egyesek adott nyelvekre vannak optimalizálva, például oroszra, kínaira vagy angolra, míg mások több nyelven is használhatók.
A valóság ennél bonyolultabb. Sok karakter több kódolásban is közös, de az egyes kódolások eltérő bájtsorozatokat használhatnak ezen karakterek tárolására a memóriában vagy a lemezen. A karakterkódolásra emiatt egyfajta visszafejtési kulcsként gondolhatsz. Amikor valakitől kapsz egy bájtsorozatot – egy fájlt, weboldalt, akármit – és azt mondja, hogy ez „szöveg”, akkor a bájtok karakterekké dekódolásához tudnod kell, hogy melyik karakterkódolást használta. Ha rossz kulcsot kapsz, vagy nem is kapsz kulcsot, akkor magadra maradsz a kód feltörésének irigylésre nem méltó feladatával. Esélyes, hogy elrontod, az eredmény pedig értelmetlen zagyvaság lesz.
Bizonyára láttál már olyan weboldalakat, mint ez, amelyek fura kérdőjelszerű karaktereket tartalmaztak az aposztrófok vagy az ékezetes betűk helyén. Ez általában azt jelenti, hogy az oldal szerzője nem adta meg a karakterkódolását, a böngésződ pedig csak találgatni tudott, amelynek eredménye várt és váratlan karakterek keveréke lett. Angolul az ilyesmi csak zavaró, de más nyelveken, például magyarul az eredmény teljesen olvashatatlan is lehet.
A világ minden jelentős nyelvéhez léteznek karakterkódolások. Mivel minden nyelv különböző, és a memória- és lemezterület történelmileg drága volt, minden karakterkódolás az adott nyelvre van optimalizálva. Ez alatt azt értem, hogy minden kódolás ugyanazokat a számokat(0–255) használta az adott nyelv karaktereinek ábrázolására. Például valószínűleg ismered az ASCII kódolást, amely az angol karaktereket 0 - 127 közti számokként tárolja. (A 65 a nagybetűs „A”, a 97 a kisbetűs „a” stb.) Az angol ábécé nagyon egyszerű, így teljes egészében leírható kevesebb, mint 128 számmal. Azok számára, akik tudnak 2-es alapon számolni, ez egy bájt 8 bitjéből 7-et jelent.
Az olyan nyugat-európai nyelvek, mint a francia, spanyol és német, több betűvel rendelkeznek, mint az angol. Pontosabban vannak mellékjelekkel kombinált betűik, mint a ñ
karakter a spanyolban. A leggyakoribb kódolás ezekhez a nyelvekhez a CP-1252, amelyet „windows-1252”-nek is neveznek, mert széles körben használatos Microsoft Windowson. A CP-1252 kódolás átveszi az ASCII kódolás által a 0–127 tartományban használt karaktereket, de aztán kiterjed a 128–255 tartományra az olyan karakterekhez, mint az n hullámvonallal (241), ü (252) stb. Ez továbbra is egybájtos kódolás, a legnagyobb lehetséges szám, a 255 továbbra is elfér egy bájton.
Egyes nyelvek, például a kínai, japán és koreai olyan sok karakterrel rendelkeznek, hogy több-bájtos karakterkészleteket igényelnek. Ez azt jelenti, hogy minden„karaktert” egy kétbájtos szám képvisel 0–65535 között. De a különböző több-bájtos kódolások ugyanazzal a problémával szembesülnek, mint a különböző egybájtos kódolások, vagyis hogy mind ugyanazokat a számokat használja különböző értelmű dolgokra. Egyszerűen csak a számok tartománya nagyobb, mert sokkal több karaktert kell ábrázolni.
Ez nagyjából rendben volt a hálózatok előtti világban, ahol a „szöveget” magadnak írtad be, és néha kinyomtattad. Nem volt sok„sima szöveg”. A forráskód ASCII volt, és mindenki más szövegszerkesztőket használt, amelyek saját (nem szöveges) formátumokat használtak, amelyek nyilvántartották a karakterkódolási információkat a gazdag formázási stílusokkal stb. együtt. Ezeket a dokumentumokat ugyanazzal a szövegszerkesztővel olvasták, mint az eredeti szerző, így minden működött, többé-kevésbé.
Most gondolj az olyan globális hálózatok felemelkedésére, mint az e-mail és a web. Rengeteg „sima szöveg” repüli körbe a földgolyót, amelyeket az egyik számítógépen írnak, a másikon továbbítanak, a harmadikon pedig fogadnak és megjelenítenek. A számítógépek csak számokat látnak, de a számok különböző dolgokat jelenthetnek. Jaj ne! Mit kéne csinálni? Nos, a rendszereket arra kellett tervezni, hogy minden „sima szöveggel” együtt átvigyék a kódolási információkat. Ne feledd, a visszafejtési kulcs képezi le a számítógépek által olvasható számokat az ember által olvasható karakterekre. Egy hiányzó visszafejtési kulcs téves, olvashatatlan vagy még rosszabb szöveget eredményez.
Most gondolj arra, hogy egy helyen több szövegdarabot kell tárolni, például ugyanabban az adatbázistáblában, amely az általad valaha kapott összes e-mailt tárolja. Ekkor is tárolni kell a karakterkódolást minden szövegdarab mellett, hogy megfelelően jeleníthesd meg. Az hiszed ez nehéz? Próbálj meg az e-mail adatbázisodban keresni, ez több kódolás közti menet közbeni konvertálást jelent. Ugye milyen jól hangzik?
Most gondolj a többnyelvű dokumentumok lehetőségére, ahol több nyelv karakterei vannak egymás mellett ugyanabban a dokumentumban. (Tipp: az ezzel próbálkozó programok általában escape kódokat használtak a „módok” közti váltáshoz. Puff, most orosz koi8-r módban vagy, így a 241 jelentése Я; puff, most Mac Greek módban vagy, így a 241 jelentése ώ.) És természetesen keresni is akarsz azokban a dokumentumokban is.
Most elbőgheted magad, mert minden, amit a karakterláncokról tudni véltél, téves, és nincs olyan, hogy „sima szöveg”.
⁂
Színre lép a Unicode.
A Unicode rendszert arra tervezték, hogy minden nyelv minden karakterét ábrázolni tudja. A Unicode minden betűt, karaktert vagy ideogrammát egy 4 bájtos számként ábrázol. Minden szám egy egyedi karaktert képvisel, amelyet legalább egy nyelvben használnak. (Nem minden szám van használatban, de több, mint 65535, így 2 bájt nem lenne elég.) A több nyelvben használt karakterek általában ugyanazzal a számmal rendelkeznek, kivéve ha komoly etimológiai érvek szólnak ez ellen. Ennek ellenére karakterenként pontosan egy szám van, és számonként pontosan egy karakter. Minden szám mindig egy dolgot jelent; nincsenek nyilvántartandó „módok”. Az U+0041
mindig az 'A'
, még ha egy adott nyelvben nincs is 'A'
karakter.
A felszínen ez jó ötletnek tűnik. Egy kódolás mind felett. Több nyelv ugyanabban a dokumentumban. Nincs több „módváltás” a kódolások adatfolyamon belüli váltásához. De azonnal adja magát a nyilvánvaló kérdés. Négy bájt? Minden egyes karakterhez‽ Ez rettenetesen pazarlónak tűnik, különösen olyan nyelvekhez, mint az angol vagy a spanyol, amelyek egy bájtnál (256 számnál) is kevesebbet igényelnek minden lehetséges karakter leírásához. Valójában még az ideogrammákat használó nyelvek (mint a kínai) esetén is pazarló, mert ezekhez sem kell karakterenként két bájtnál több soha.
Van egy Unicode kódolás, amely karakterenként négy bájtot használ. A neve UTF-32, mert 32 bit = 4 bájt. Az UTF-32 egy magától értetődő kódolás; veszi az összesUnicode karaktert (egy 4 bájtos szám), és azt a karaktert ugyanazzal a számmal ábrázolja. Ennek vannak előnyei, a legfontosabb, hogy egy karakterlánc N. karakterét állandó idő alatt lehet megtalálni, mert az N. karakter a 4×N. bájtnál kezdődik. Van sok hátránya is, a legnyilvánvalóbb, hogy négy nyomorult bájtot igényel minden nyomorult karakter tárolásához.
Noha rengeteg Unicode karakter van, a legtöbben gyakorlatilag nem fognak soha semmit használni az első 65535-ön kívül. Emiatt létezik egy másik Unicode kódolás is, az UTF-16 (mert 16 bit = 2 bájt). Az UTF-16 minden karaktert 0–65535 között tárol két bájton, és piszkos trükköket használ, ha a ritkán használt, „asztrálsíkon” lévő Unicode karaktereket kell ábrázolnod a 65535 fölött. A legnyilvánvalóbb előny: Most az UTF-16 kétszer olyan helytakarékos, mint az UTF-32, mert minden karakter tárolása pontosan két bájtot igényel csak négy bájt helyett (kivéve amelyiké nem). És még mindig egyszerűen és konstans idő alatt megtalálható egy karakterlánc N. karaktere, ha feltételezzük, hogy a karakterlánc nem tartalmazza az asztrálsíkon lévő karakterek egyikét sem. Ez egy jó feltételezés, egészen addig, amíg már nem.
Azonban az UTF-32 és az UTF-16 egyaránt rendelkezik nem nyilvánvaló hátrányokkal. A különböző számítógéprendszerek az egyes bájtokat különböző módokon tárolják. Ez azt jelenti, hogy az U+4E2D
karakter UTF-16 használatakor tárolható 4E 2D
vagy 2D 4E
formában is, attól függően, hogy a rendszer big-endian vagy little-endian. (Az UTF-32 esetén még több lehetséges bájtsorrend van.) Amíg a dokumentumaid soha nem hagyják el a számítógéped, biztonságban vagy – ugyanazon számítógép különböző alkalmazásai ugyanazt a bájtsorrendet használják. Azonban abban a percben, hogy dokumentumokat akarsz rendszerek között átvinni, mondjuk valamilyen világszintű hálózaton, akkor jelezned kell a bájtjaid tárolási sorrendjét. Ellenkező esetben a fogadó rendszer nem fogja tudni, hogy a 4E 2D
kétbájtos sorozat jelentése U+4E2D
vagy U+2D4E
.
Ennek a problémának a megoldásához a több-bájtos Unicode kódolások definiálnak egy „bájtsorrendjelet”, amely egy speciális nem nyomtatható karakter. Ezt a dokumentum elején elhelyezve jelezheted a bájtok sorrendjét. Az UTF-16 esetén a bájtsorrendjel az U+FEFF
. Ha egy FF FE
bájtokkal kezdődő UTF-16 dokumentumot kapsz, akkor a bájtsorrend az egyik, ha az FE FF
bájtokkal kezdődik, akkor a bájtsorrend a másik.
Az UTF-16 ezzel együtt sem teljesen ideális, különösen ha rengeteg ASCII karakterrel dolgozol. Ha belegondolsz, akkor még egy kínai weboldal is rengeteg ASCII karaktert fog tartalmazni – a nyomtatható kínai karaktereket körülvevő összes elemet és attribútumot. Az N. karakter konstans idő alatti megtalálása szép dolog, de még itt van az asztrálsíkon lévő karakterek kellemetlen problémája, ami miatt nem tudod garantálni, hogy minden karakter pontosan két bájtos, emiatt nem lehet valóban megtalálni az N. karaktert konstans idő alatt, hacsak nem tartasz fenn egy külön indexet. És tudod, annyi de annyi ASCII szöveg van a világban…
Mások is gondolkoztak ezeken a kérdéseken, és kitaláltak egy megoldást:
UTF-8
Az UTF-8 egy változó hosszúságú kódolási rendszer a Unicode-hoz. Ez azt jelenti, hogy különböző karakterek különböző számú bájtot foglalnak. Az ASCII karakterekhez (A-Z stb.) az UTF-8 karakterenként csak egy bájtot használ. Tulajdonképpen pontosan ugyanazokat a bájtokat használja. Az UTF-8 első 128 karaktere (0–127) megkülönböztethetetlen az ASCII-étól. A „kiterjesztett latin” karakterek, mint a ñ és ö két bájtot foglalnak. (A bájtok nem egyszerűen az Unicode kódpontot jelentik, mint UTF-16 esetén; komoly bittologatás is szerepet kap.) A kínai karakterek, mint a 中 három bájtot foglalnak. A ritkán használt „asztrálsík” karakterek négy bájtot.
Hátrányok: mivel minden karakter különböző számú bájtot foglalhat, az N. karakter megkeresése egy O(N) művelet – azaz minél hosszabb a karakterlánc, annál tovább tart egy adott karakter megkeresése. Ezen kívül bittologatás szükséges a karakterek bájtokká kódolásához és a bájtok visszafejtéséhez karakterekké.
Előnyök: az általános ASCII karakterek kódolása szuperhatékony. Nem rosszabb az UTF-16-nál a kiterjesztett latin karakterek esetén. Jobb az UTF-32-nél a kínai karakterekhez. Ezen túl (és ezt el kell hinned nekem, mert nem fogom megmutatni a matekját) pontosan a bittologatás természete miatt nincsenek problémák a bájtsorrendből. Egy UTF-8 kódolású dokumentum pontosan ugyanazt a bájtsorozatot használja minden számítógépen.
⁂
A Python 3-ban minden karakterlánc Unicode karakterek sorozata. Nincs olyan, hogy UTF-8 kódolású Python karakterlánc, vagy CP-1252 kódolású Python karakterlánc. Az „UTF-8 ez a karakterlánc?” kérdés érvénytelen. Az UTF-8 a karakterek bájtok sorozataként való kódolásának módja. Ha egy adott karakterláncot át szeretnél alakítani adott karakterkódolású bájtok sorozatává, akkor a Python 3 megoldja. Ha egy adott bájtsorozatot karakterlánccá szeretnél alakítani, akkor a Python 3 azt is megoldja. A bájtok nem karakterek, a bájtok bájtok. A karakter egy absztrakció. Egy karakterlánc ezen absztrakciók sorozata.
>>> s = '深入 Python' ① >>> len(s) ② 9 >>> s[0] ③ '深' >>> s + ' 3' ④ '深入 Python 3'
'
) vagy dupla idézőjelekkel ("
).
len()
függvény visszaadja a karakterlánc hosszát, azaz a karakterek számát. Ez ugyanaz a függvény, amit a listák, tuple-ök, halmazok vagy szótárak hosszának meghatározására használtál. A karakterlánc olyan, mint egy karaktertuple.
+
operátor használatával.
⁂
Vessünk még egy pillantást a humansize.py
programra:
SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], ①
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
def approximate_size(size, a_kilobyte_is_1024_bytes=True):
'''Egy fájlméret emberek által olvasható formába konvertálása. ②
Kulcsszó argumentumok:
size -- a fájlméret bájtban
a_kilobyte_is_1024_bytes -- ha True (alapértelmezett), akkor az 1024 többszöröseit használja
ha False, akkor az 1000 többszöröseit használja
Visszaad: karakterláncot
''' ③
if size < 0:
raise ValueError('a szám nem lehet negatív') ④
multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
for suffix in SUFFIXES[multiple]:
size /= multiple
if size < multiple:
return '{0:.1f} {1}'.format(size, suffix) ⑤
raise ValueError('a szám túl nagy')
'KB'
, 'MB'
, 'GB'
… ezek mind karakterláncok.
A Python 3 támogatja az értékek karakterláncokba formázását. Noha ez nagyon bonyolult kifejezéseket is tartalmazhat, a legalapvetőbb felhasználási módja egy értéknek helykitöltőt tartalmazó karakterláncba való beszúrása.
>>> felhasználó = 'mark' >>> jelszó = 'PapayaWhip' ① >>> "{0} jelszava ez: {1}".format(felhasználó, jelszó) ② "mark jelszava ez: PapayaWhip"
{0}
és a {1}
helyettesítőmezők, amelyeket a format()
metódusnak átadott argumentumok helyettesítenek.
Az előző példa a legegyszerűbb esetet mutatja be, ahol a helyettesítőmezők egyszerű egészek. Az egész helyettesítőmezők helyzeti indexekként vannak kezelve a format()
metódus argumentumlistájában. Ez azt jelenti, hogy a {0}
az első argumentummal lesz helyettesítve (felhasználó ebben az esetben), a {1}
a második argumentummal lesz helyettesítve (jelszó) stb. Annyi helyzeti indexed lehet, ahány argumentumod van, és annyi argumentumod lehet, amennyit csak akarsz. De a helyettesítőmezők ennél sokkal hatékonyabbak.
>>> import humansize >>> si_suffixes = humansize.SUFFIXES[1000] ① >>> si_suffixes ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] >>> '1000{0[0]} = 1{0[1]}'.format(si_suffixes) ② '1000KB = 1MB'
humansize
modul valamelyik függvényének hívása helyett csak az általa definiált egyik adatszerkezetet használjuk: az „SI” utótagok (ezek 1000 hatványai) listáját.
{0}
a format()
metódusnak elsőként átadott argumentumra, az si_suffixes-re hivatkozik. De az si_suffixes egy lista. Így a {0[0]}
a lista első elemére hivatkozik, ez lesz a format()
metódusnak átadott első argumentum: 'KB'
. Ezalatt a {0[1]}
ugyanazon lista második elemére hivatkozik: 'MB'
. A kapcsos zárójeleken kívül minden – beleértve az 1000
-t, az egyenlőségjelet és a szóközket – érintetlen. A végeredmény a következő karakterlánc:'1000KB = 1MB'
.
Ez a példa azt mutatja meg, hogy a formátumelőírások az adatszerkezetek elemeit és tulajdonságait (majdnem) Python szintaxissal tudják elérni. Ezeket összetett mezőneveknek hívjuk. A következő összetett mezőnevek „egyszerűen csak működnek”:
Csak hogy ne alhass nyugodtan, itt egy példa, amely a fentiek mindegyikét kombinálja:
>>> import humansize >>> import sys >>> '1MB = 1000{0.modules[humansize].SUFFIXES[1000][0]}'.format(sys) '1MB = 1000KB'
Így működik:
sys
modul információkat tárol az éppen futó Python példányról. Mivel importáltad, átadhatod magát a sys
modult a format()
metódus argumentumaként. Így a {0}
helyettesítőmező a sys
modulra hivatkozik.
sys.modules
az aktuális Python példányba importált összes modult tartalmazó szótár. A kulcsok a modulnevek karakterláncokként, az értékek maguk a modulobjektumok. Így a {0.modules}
helyettesítőmező az importált modulok szótárára hivatkozik.
sys.modules['humansize']
az éppen importált humansize
modul. A {0.modules[humansize]}
helyettesítőmező a humansize
modulra hivatkozik. Vedd észre az apró eltérést a szintaxisban. Valódi Python kódban a sys.modules
szótár kulcsai karakterláncok, a rájuk való hivatkozáshoz idézőjelek közé kell tenned a modulnevet (például: 'humansize'
). Helyettesítőmezőben azonban el kell hagyni a szótárkulcs neve körüli idézőjeleket (például: humansize
). A PEP 3101: speciális karakterlánc-formázás szerint: „Az elem kulcsának feldolgozási szabályai nagyon egyszerűek. Ha számjeggyel kezdődik, akkor számként lesz kezelve, ellenkező esetben karakterláncként.”
sys.modules['humansize'].SUFFIXES
a humansize
modul elején definiált szótár. A {0.modules[humansize].SUFFIXES}
helyettesítőmező erre a szótárra hivatkozik.
sys.modules['humansize'].SUFFIXES[1000]
az SI-utótagok listája: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
. Így a {0.modules[humansize].SUFFIXES[1000]}
helyettesítőmező erre a listára hivatkozik.
sys.modules['humansize'].SUFFIXES[1000][0]
az SI-utótagok listájának első eleme: 'KB'
. Emiatt a teljes {0.modules[humansize].SUFFIXES[1000][0]}
helyettesítőmező a két karakterből álló KB
karakterláncra lesz cserélve.
Várj csak! Van még más is! Nézzük meg újra ezt a fura sort a humansize.py
fájlból:
if méret < multiple:
return '{0:.1f} {1}'.format(méret, utótag)
Az {1}
a format()
metódusnak átadott második argumentumra lesz cserélve, amely az utótag. De mi ez a {0:.1f}
? Ez két dolog: a {0}
, amit már felismersz, és a :.1f
, amit még nem. A második fele (a kettőspont és ami utána áll) definiálja a formátum-előírást, amely tovább finomítja a helyettesített változó formázásának módját.
☞A formátum-előírások lehetővé teszik a helyettesítőszöveg változatos módokon való megpiszkálását, mint a C
printf()
függvényében. Hozzáadhatsz nulla- vagy szóközkitöltést, igazíthatod a karakterláncokat, befolyásolhatod a tizedesjegyek számát, és akár hexadecimálissá is alakíthatsz számokat.
A helyettesítőmezőn belül egy kettőspont (:
) jelöli a formátum-előírás kezdetét. A „.1
” formátum-előírás „a legközelebbi tizedesre kerekítést” jelent (azaz csak egy számjegy jelenik meg a tizedesvessző után). Az „f
” formátum-előírás „fixpontos számot” jelöl (nem pedig exponenciális jelölést vagy más decimális ábrázolást). Emiatt a 698.24
méret és a 'GB'
utótag esetén a formázott karakterlánc '698.2 GB'
lesz, mert a 698.24
egy tizedesjegyre lesz kerekítve, majd az utótag a szám mögé lesz fűzve.
>>> '{0:.1f} {1}'.format(698.24, 'GB') '698.2 GB'
A formátum-előírásokkal kapcsolatos véres részletekért olvasd el a Format Specification Mini-Language oldalt a hivatalos Python dokumentációban.
⁂
A formázás mellett a karakterláncok sok más hasznos trükköt is tudnak.
>>> s = '''A befejezett tanul- ① ... mányok több évnyi tudományos mun- ... ka és az évek tapasztala- ... tának egyesített eredménye.''' >>> s.splitlines() ② ['A befejezett tanul-', 'mányok több évnyi tudományos mun-', 'ka és az évek tapasztala-', 'tának egyesített eredménye.'] >>> print(s.lower()) ③ a befejezett tanul- mányok több évnyi tudományos mun- ka és az évek tapasztala- tának egyesített eredménye. >>> s.lower().count('m') ④ 4
splitlines()
metódus egy többsoros karakterláncot vár, és karakterláncok listáját adja vissza, az eredeti minden sorához egyet rendelve. Ne feledd, hogy a sorok végén lévő kocsivissza karaktereket ez nem tartalmazza.
lower()
metódus az egész karakterláncot kisbetűssé alakítja. (Hasonlóan, az upper()
metódus egy karakterláncot nagybetűssé alakít.)
count()
metódus megszámolja egy részkarakterlánc előfordulásainak számát. Igen, ebben a mondatban tényleg négy „m” van!
Itt van még egy gyakori eset. Mondjuk, hogy van egy kulcs-érték párokat tartalmazó listád, a következő formátumban: kulcs1=érték1&kulcs2=érték2
; és fel szeretnéd darabolni ezeket, hogy az egészet betehesd egy {kulcs1: érték1, kulcs2: érték2}
alakú szótárba.
>>> lekérdezés = 'felhasználó=pilgrim&adatbázis=master&jelszó=PapayaWhip' >>> a_list = lekérdezés.split('&') ① >>> a_list ['felhasználó=pilgrim', 'adatbázis=master', 'jelszó=PapayaWhip'] >>> a_list_of_lists = [v.split('=', 1) for v in a_list if '=' in v] ② >>> a_list_of_lists [['felhasználó', 'pilgrim'], ['adatbázis', 'master'], ['jelszó', 'PapayaWhip']] >>> a_dict = dict(a_list_of_lists) ③ >>> a_dict {'jelszó': 'PapayaWhip', 'felhasználó': 'pilgrim', 'adatbázis': 'master'}
split()
karakterlánc-metódus egy kötelező argumentummal, a határolóval rendelkezik. A metódus a karakterláncot a határoló alapján karakterláncok listájává darabolja. Itt a határoló az & karakter, de bármi lehet.
split()
metódus elhagyható második argumentuma a szétvágások kívánt száma. Az 1
„csak egy szétvágást” jelent, így asplit()
metódus egy kételemű listát fog visszaadni. (Elméletileg egy érték is tartalmazhat egyenlőségjelet. Ha a 'kulcs=érték=valami'.split('=')
hívást használtad volna, akkor a ['kulcs', 'érték', 'valami']
háromelemű listát kaptad volna.)
dict()
függvénynek való átadással.
☞Az előző példa nagyon úgy néz ki, mint egy URL lekérésparamétereinek feldolgozása, de a valós életben az URL-feldolgozás valójában ennél sokkal bonyolultabb. Ha URL-lekérdezésparaméterekkel dolgozol, akkor jobban jársz az
urllib.parse.parse_qs()
függvénnyel, amely kezel néhány nem nyilvánvaló határesetet is.
Miután definiáltál egy karakterláncot, bármely részét megkaphatod új karakterláncként. Ezt a karakterlánc szeletelésének nevezzük. A szeletelés pontosan ugyanúgy működik, mint a listák szeletelése, ami logikus is, hiszen a karakterláncok pusztán karakterek sorozatai.
>>> a_string = 'Az én ábécém ott kezdődik, ahol a tiéd véget ér.' >>> a_string[6:12] ① 'ábécém' >>> a_string[6:-6] ② 'ábécém ott kezdődik, ahol a tiéd vég' >>> a_string[0:2] ③ 'Az' >>> a_string[:25] ④ 'Az én ábécém ott kezdődik' >>> a_string[25:] ⑤ ', ahol a tiéd véget ér.'
a_string[0:2]
a karakterlánc első két elemét adja vissza az a_string[0]
elemtől az a_string[2]
elemig, de az utóbbit már nem tartalmazza.
a_string[:25]
ugyanaz, mint az a_string[0:25]
mert a kezdő 0-t a Python feltételezi.
a_string[25:]
ugyanaz, mint az
a_string[25:48]
, mert ez a karakterlánc 48 karaktert tartalmaz. Van itt egy kellemes szimmetria. Ebben a 48 karakteres karakterláncban az a_string[:25]
visszaadja az első 25 karaktert, és az a_string[25:]
visszaad mindent az első 25 karakter kivételével. Tulajdonképpen az a_string[:n]
mindig az első n karaktert adja vissza, az
a_string[n:]
pedig a többit, a karakterlánc hosszától
függetlenül.
⁂
A bájtok bájtok; a karakterek absztrakciók. Unicode karakterek megváltoztathatatlan sorozatát karakterláncnak hívjuk. A 0 és 255 közötti számok megváltoztathatatlan sorozatát bájtobjektumnak hívjuk.
>>> by = b'abcd\x65' ① >>> by b'abcde' >>> type(by) ② <class 'bytes'> >>> len(by) ③ 5 >>> by += b'\xff' ④ >>> by b'abcde\xff' >>> len(by) ⑤ 6 >>> by[0] ⑥ 97 >>> by[0] = 102 ⑦ Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'bytes' object does not support item assignment
bájtobjektum
definiálásához használd a b''
„bájtliterál” szintaxist. A bájtliterálon belül minden bájt lehet egy ASCII karakter, vagy egy kódolt hexadecimális szám \x00
és \xff
(0–255) között.
bájtobjektum
típusa bytes
.
len()
függvénnyel lekérheted a bájtobjektum
hosszát.
+
operátort a bájtobjektumok
összefűzésére. Az eredmény egy új bájtobjektum
.
bájtobjektum
és egy 1 bájtos bájtobjektum
összefűzése egy 6 bájtos bájtobjektumot
eredményez.
bájtobjektum
egyes bájtjai elérhetők indexelés használatával. Egy karakterlánc elemei karakterláncok, egy bájtobjektum
elemei egészek. Egész pontosan 0–255 közti egészek.
bájtobjektum
megváltoztathatatlan, nem adhatsz értéket az egyes bájtoknak. Ha az egyes bájtokat kell módosítanod, akkor használhatsz karakterláncszeletelést és összefűzési operátorokat (ezek ugyanúgy működnek, mint a karakterláncok), vagy átalakíthatod a bájtobjektumot
bájttömb
objektummá.
>>> by = b'abcd\x65' >>> btmb = bytearray(by) ① >>> btmb bytearray(b'abcde') >>> len(btmb) ② 5 >>> btmb[0] = 102 ③ >>> btmb bytearray(b'fbcde')
bájtobjektum
megváltoztatható bájttömb
objektummá alakításához használd a beépített bytearray()
függvényt.
bájtobjektumokon
használható metódus és művelet működik bájttömb
objektumokon is.
bájttömb
objektum esetén értékeket rendelhetsz az egyes bájtokhoz indexelés használatával. A hozzárendelt értéknek egy 0–255 közti egésznek kell lennie.
Az egyetlen dolog, amit soha nem csinálhatsz, az a bájtok és karakterláncok keverése.
>>> by = b'd' >>> s = 'abcde' >>> by + s ① Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't concat bytes to str >>> s.count(by) ② Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't convert 'bytes' object to str implicitly >>> s.count(by.decode('ascii')) ③ 1
Itt jön a kapcsolat a karakterláncok és a bájtok között: a bájtobjektumok
rendelkeznek egy decode()
metódussal, amely egy karakterkódolást vár, és visszaad egy karakterláncot, a karakterláncok pedig rendelkeznek egy encode()
metódussal, amely egy karakterkódolást vár és egy bájtobjektumot
ad vissza. Az előző példában a dekódolás viszonylag magától érthetődő volt – egy ASCII kódolású bájtsorozat átalakítása történt karakterek sorozatává. De ugyanez a folyamat történik bármely kódolással, amley támogatja a karakterlánc karaktereit – még az örökölt(nem Unicode) kódolások esetén is.
>>> a_string = '深入 Python' ① >>> len(a_string) 9 >>> by = a_string.encode('utf-8') ② >>> by b'\xe6\xb7\xb1\xe5\x85\xa5 Python' >>> len(by) 13 >>> by = a_string.encode('gb18030') ③ >>> by b'\xc9\xee\xc8\xeb Python' >>> len(by) 11 >>> by = a_string.encode('big5') ④ >>> by b'\xb2`\xa4J Python' >>> len(by) 11 >>> roundtrip = by.decode('big5') ⑤ >>> roundtrip '深入 Python' >>> a_string == roundtrip True
bájtobjektum
. 13 bájtból áll. Ez az a bájtsorozat, amelyet az a_string UTF-8-ba kódolásakor kapsz.
bájtobjektum
. 11 bájtból áll. Ez az a bájtsorozat, amelyet az a_string GB18030-ba
kódolásakor kapsz.
bájtobjektum
. 11 bájtból áll. Ez egy teljesen eltérő bájtsorozat, amelyet az a_string Big5-ba kódolásakor kapsz.
⁂
A Python 3 feltételezi, hogy a forráskódod – azaz minden .py
fájl – UTF-8 kódolású.
☞A Python 2-ben a
.py
fájlok alapértelmezett kódolása ASCII volt. A Python 3-ban az alapértelmezett kódolás az UTF-8.
Ha másik kódolást szeretnél használni a Python kódodon belül, akkor elhelyezhetsz egy kódolásdeklarációt az egyes fájlokon belül. Ez a deklaráció a .py
fájlt windows-1252 kódolásúként definiálja:
# -*- coding: windows-1252 -*-
Technikailag a karakterkódolás felülbírálása a második sorban is lehet, ha az első sor egy UNIX-stílusú shebang parancs.
#!/usr/bin/python3
# -*- coding: windows-1252 -*-
További információkért olvasd el a PEP 263: Defining Python Source Code Encodings dokumentumot.
⁂
A Unicode-ról a Pythonban:
A Unicode-ról általában:
A karakterkódolásról más formátumokban:
Karakterláncokról és azok formázásáról:
string
– Gyakori karakterlánc-műveletek
© 2001–11 Mark Pilgrim