Sala de studiu Karinoya

Calificări · Laboratorul de promovare Cloud / AI / Python

Tipuri și șiruri de caractere în Python

Puteți citi întrebările și explicațiile în Română. Lecțiile (articolele explicative) sunt disponibile doar în japoneză.

Vedeți versiunea în japoneză (cu lecții) →

Î1 | Manualul principal

Care este manualul principal corect pentru Examenul de bază pentru certificarea inginerilor Python 3?

  1. 『Pythonチュートリアル』(Tutorialul Python), publicat de オライリー・ジャパン (O'Reilly Japan)
  2. 『あたらしいデータ分析の教科書』(Noul manual de analiză a datelor), publicat de 翔泳社 (Shoeisha)
  3. 『Pythonデータ分析 実践ハンドブック』(Manual practic de analiză a datelor în Python), publicat de インプレス (Impress)
  4. 『Python実践レシピ』(Rețete practice Python), publicat de 技術評論社 (Gijutsu-Hyoronsha)
Răspuns corectA. 『Pythonチュートリアル』(Tutorialul Python), publicat de オライリー・ジャパン (O'Reilly Japan)

Manualul principal al examenului de bază este 『Pythonチュートリアル』, publicat de オライリー・ジャパン; pagina oficială indică faptul că, începând cu 1 septembrie 2021, se corelează cu ediția a 4-a. Și programa de examinare este publicată pe baza numerotării și titlurilor capitolelor din această carte, deci pregătirea înseamnă parcurgerea conținutului acestei cărți, ponderat pe capitole. 『Python実践レシピ』 de la 技術評論社 este manualul examenului practic, 『Pythonによるあたらしいデータ分析の教科書』 de la 翔泳社 este manualul examenului de analiză a datelor, iar 『Pythonデータ分析 実践ハンドブック』 de la インプレス este manualul examenului practic de analiză a datelor — toate sunt manuale ale altor examene organizate de aceeași asociație. Confundarea manualelor duce la a studia îndelung materie din afara programei, deci merită verificat de la bun început.

Î2 | Capitolul cu cele mai multe întrebări

În programa examenului de bază, din care capitol al manualului principal provin cele mai multe întrebări?

  1. Capitolul 5, „Structuri de date”
  2. Capitolul 4, „Instrumente de control al fluxului”
  3. Capitolul 3, „O introducere relaxată”
  4. Capitolul 8, „Erori și excepții”
Răspuns corectB. Capitolul 4, „Instrumente de control al fluxului”

Cel mai mare este capitolul 4, „Instrumente de control al fluxului”, căruia îi sunt alocate 9 din cele 40 de întrebări. Urmează capitolul 5, „Structuri de date”, cu 7, apoi capitolul 3, „O introducere relaxată”, cu 6, iar capitolul 8, „Erori și excepții”, are 4. Doar capitolele 3, 4 și 5 însumează 22 de întrebări, adică peste jumătate din total. Prin urmare, este rațional ca și timpul de studiu să fie alocat mai ales acestor trei capitole, iar amânarea capitolului 4, care tratează instrucțiunea for și definirea funcțiilor, poate fi ireparabilă.

Î3 | Distribuția pe capitole

În programa examenului de bază, ce pondere ocupă capitolul 4, „Instrumente de control al fluxului”?

  1. 17,5%
  2. 10,0%
  3. 22,5%
  4. 15,0%
Răspuns corectC. 22,5%

Capitolul 4, „Instrumente de control al fluxului”, are 9 din 40 de întrebări, adică 22,5%. Este cel mai mare pe capitole, urmat de capitolul 5, „Structuri de date”, cu 7 întrebări, adică 17,5%. 15,0% corespunde celor 6 întrebări din capitolul 3, „O introducere relaxată”, iar 10,0% corespunde celor 4 întrebări din capitolul 8, „Erori și excepții”, respectiv din capitolul 10, „Turul bibliotecii standard”. Această distribuție nu este o cifră operațională, ci este publicată chiar ca parte a programei de examinare, deci poate fi folosită ca bază pentru planul de studiu.

Î4 | Distribuția capitolului 13

În programa examenului de bază, câte întrebări sunt alocate capitolului 13, „Ce urmează?”?

  1. 0 întrebări
  2. 1 întrebare
  3. 4 întrebări
  4. 2 întrebări
Răspuns corectA. 0 întrebări

Capitolul 13, „Ce urmează?”, are 0 întrebări — este singurul capitol din programă care nu apare deloc la examen. Conținutul lui ghidează pașii următori în învățare, deci este exclus dintr-un examen axat pe gramatică. Câte o întrebare este alocată capitolelor 1, 2, 7, 11, 12 și 14, câte 2 capitolelor 6 și 9, iar câte 4 capitolelor 8, „Erori și excepții”, și 10, „Turul bibliotecii standard”. Cu excepția capitolului 13, toate celelalte au cel puțin o întrebare, deci merită să se parcurgă terminologia măcar și pentru capitolele cu pondere mică.

Î5 | Parametrul sep al lui print

Care este șirul de caractere afișat pe ecran la rularea următorului program?

print('Python', 3, 'exam', sep='/')
  1. Python3exam
  2. Python 3 exam
  3. Python/3/exam/
  4. Python/3/exam
Răspuns corectD. Python/3/exam

print() leagă argumentele primite folosind parametrul cu cuvânt-cheie sep. Valoarea implicită pentru sep este un singur spațiu, deci fără să fie specificat rezultatul ar fi Python 3 exam, dar aici se specifică sep='/', deci argumentele sunt legate prin bară oblică și rezultă Python/3/exam. Python3exam ar fi rezultatul dacă sep ar fi un șir vid. A alege Python/3/exam/, cu un separator și la final, corespunde ideii greșite că sep se adaugă după fiecare element — de fapt, se inserează doar între argumente. Cel care apare la final este end, nu sep.

Î6 | Parametrul end al lui print

La rularea următoarelor 3 linii, în ordine, ce apare pe ecran?

print('A', end='')print('B', end='')print('C')
  1. AB și C se afișează pe 2 linii
  2. Se afișează doar ABC, pe o singură linie
  3. Se afișează doar A B C, pe o singură linie
  4. A, B, C se afișează pe 3 linii
Răspuns corectB. Se afișează doar ABC, pe o singură linie

print() adaugă la sfârșitul ieșirii parametrul cu cuvânt-cheie end. Valoarea implicită este caracterul de linie nouă, deci, fără să fie specificat, fiecare apel al lui print() trece pe linie nouă. Aici, pentru primele două apeluri s-a folosit end='', oprind trecerea pe linie nouă, așa că A și B sunt afișate consecutiv, iar ultimul print() adaugă linia nouă implicită, astfel încât rezultă doar ABC, pe o singură linie. A B C, cu spații, ar apărea dacă s-ar fi pasat trei argumente unui singur print(); afișarea pe 3 linii ar corespunde cazului în care end nu ar fi fost specificat deloc; afișarea pe 2 linii ar corespunde cazului în care doar unul dintre cele două end='' ar fi fost omis.

Î7 | Afișare cu despachetare

Care este rezultatul următorului program, care despachetează și afișează o listă?

nums = [10, 20, 30]print(*nums, sep=', ')
  1. Se afișează 10, 20, 30
  2. Se afișează 102030
  3. Se afișează [10, 20, 30]
  4. Se afișează 10 20 30
Răspuns corectA. Se afișează 10, 20, 30

print(*nums), cu asterisc, trece fiecare element al listei către print() ca argument separat. Astfel, cele trei argumente sunt legate cu sep, iar cum sep=', ', rezultatul este 10, 20, 30. Fără asterisc, print(nums) trece lista ca un singur argument, deci apare direct [10, 20, 30], cu paranteze pătrate. Fără specificarea lui sep, s-ar folosi implicit spațiul, rezultând 10 20 30, iar cu sep='' rezultatul ar fi lipit, 102030.

Î8 | Simbolul comentariului

Care este descrierea corectă pentru comentariile în Python?

  1. Tot ce este cuprins între /* și */ este ignorat ca și comentariu
  2. Tot ce urmează după # până la sfârșitul liniei este ignorat ca și comentariu
  3. Tot ce urmează după -- până la sfârșitul liniei este ignorat ca și comentariu
  4. Tot ce urmează după // până la sfârșitul liniei este ignorat ca și comentariu
Răspuns corectB. Tot ce urmează după # până la sfârșitul liniei este ignorat ca și comentariu

Comentariile în Python se scriu cu simbolul diez, iar tot ce urmează, până la sfârșitul liniei, este ignorat. Dacă este pus la începutul liniei, toată linia devine comentariu; dacă este pus la mijloc, doar restul liniei. Nu există o sintaxă dedicată pentru a cuprinde mai multe linii deodată, așa că diezul se pune pe fiecare linie în parte. Scrierea între ghilimele triple este uneori folosită în locul unui bloc de comentariu, dar acesta este, din punct de vedere sintactic, un literal de tip șir de caractere; pus la începutul unei funcții sau clase, este păstrat la rulare ca docstring. Bara dublă este în Python operatorul de împărțire cu rest la podea, iar bara-asterisc și dublul-cratimă sunt notații de comentariu din alte limbaje.

Î9 | Indentarea

Ce se întâmplă dacă următorul program este salvat într-un fișier și rulat?

if True:    print('one')        print('two')
  1. Se afișează doar two, iar procesarea se încheie
  2. Se afișează doar one, iar procesarea se încheie
  3. Se afișează, în această ordine, one și two
  4. Se produce IndentationError și execuția se oprește
Răspuns corectD. Se produce IndentationError și execuția se oprește

Python marchează blocurile prin adâncimea indentării, deci instrucțiunile din același bloc trebuie să aibă indentarea aliniată. Doar linia a 3-a este mai adâncă, iar linia dinaintea ei nu este o linie care introduce un bloc nou (adică nu se termină cu două puncte), deci apare IndentationError: unexpected indent. Aceasta este detectată la analiza sintactică, înainte de execuție, deci nici măcar print-ul de pe linia a 2-a nu se execută, iar one nici măcar nu se afișează. Dacă indentarea lipsește acolo unde e necesară, mesajul este expected an indented block, iar dacă adâncimea nu se potrivește pe parcurs, unindent does not match any outer indentation level — dar în ambele cazuri este vorba tot de IndentationError.

Î10 | Codificarea caracterelor

Care este descrierea corectă privind codificarea caracterelor fișierelor sursă în Python 3?

  1. Shift_JIS este implicită și poate fi schimbată printr-o declarație
  2. UTF-8 este implicită, iar japoneza poate fi scrisă direct
  3. EUC-JP este implicită, iar japoneza poate fi scrisă direct
  4. ASCII este implicită, iar pentru a include japoneza este nevoie de o declarație
Răspuns corectB. UTF-8 este implicită, iar japoneza poate fi scrisă direct

Fișierele sursă Python 3 sunt citite implicit ca UTF-8, deci se poate scrie japoneza direct atât în comentarii, cât și în literalii de tip șir de caractere. În Python 2, implicit era ASCII, iar pentru a include japoneza era nevoie de o declarație de codificare (coding) pe prima sau a doua linie a fișierului; în Python 3 această declarație nu mai este necesară. Declarația se scrie doar dacă se dorește citirea unui fișier salvat cu o altă codificare decât UTF-8. De asemenea, se pot folosi caractere japoneze și în identificatori (nume de variabile sau funcții), dar acest lucru nu este recomandat din motive de lizibilitate.

Î11 | Tipul rezultat din împărțire

Următorul program tratează împărțirea a două numere întregi și afișează valoarea pe prima linie, iar numele tipului pe a doua. Care este combinația corectă?

print(9 / 3)print(type(9 / 3).__name__)
  1. Valoarea este 3.0, tipul este int
  2. Valoarea este 3.0, tipul este float
  3. Valoarea este 3, tipul este int
  4. Valoarea este 3, tipul este float
Răspuns corectB. Valoarea este 3.0, tipul este float

O singură bară oblică / este împărțirea reală, iar rezultatul este întotdeauna float. Nici cazul în care împărțirea este exactă nu face excepție, deci 9 / 3 este 3.0, nu 3, iar tipul este float. Dacă se presupune că, fiind vorba de numere întregi, rezultatul trebuie să fie int, se alege greșit combinația 3 și int; pentru a obține un int, trebuie folosită împărțirea cu rest la podea, adică 9 // 3, care dă 3 de tip int. Combinațiile în care valoarea afișată nu se potrivește cu tipul, precum 3 cu float sau 3.0 cu int, nu apar din această expresie.

Î12 | Împărțirea la podea cu numere negative

Care este rezultatul următorului program, care înșiruie mai multe împărțiri la podea?

print(9 // 4)print(-9 // 4)
  1. Prima linie 2.0, a doua linie -3.0
  2. Prima linie 2, a doua linie -3
  3. Prima linie 2.25, a doua linie -2.25
  4. Prima linie 2, a doua linie -2
Răspuns corectB. Prima linie 2, a doua linie -3

Bara dublă // este împărțirea la podea, care rotunjește câtul în jos, adică spre valoarea mai mică pe axa numerelor. 9 / 4 este 2.25, deci 9 // 4 este 2; -9 / 4 este -2.25, deci -9 // 4 nu este -2, ci -3. Punctul-cheie este că rotunjirea nu se face spre 0; alegerea -2 corespunde ideii greșite că rotunjirea se face spre 0, ca în limbajul C. 2.25 și -2.25 sunt valorile obținute cu / în loc de //, iar 2.0 și -3.0 ar corespunde amestecării unui float printre operanzi, ca în 9.0 // 4 — dacă ambii operanzi sunt int, și rezultatul este int.

Î13 | divmod

Ce valoare returnează divmod(-11, 3)?

  1. (-4, 1)
  2. (-3, -2)
  3. (-4, -2)
  4. (-3, 2)
Răspuns corectA. (-4, 1)

divmod(a, b) returnează tuplul (a // b, a % b). Deoarece // în Python rotunjește spre podea, -11 // 3 este -4, iar semnul restului este aliniat la deîmpărțitor, deci -11 % 3 este 1. Prin urmare, rezultatul este (-4, 1). Dacă s-ar gândi în stilul rotunjirii spre 0, câtul ar fi -3, iar restul -2, alegându-se greșit (-3, -2), dar Python nu folosește această convenție. Câtul și restul păstrează întotdeauna relația deîmpărțitor înmulțit cu câtul plus restul egal cu valoarea originală, deci 3 înmulțit cu -4 plus 1 dă -11, ceea ce confirmă rezultatul. Verificând cu această relație, nici (-3, 2), nici (-4, -2) nu redau -11.

Î14 | Rotunjirea prin int

Care este rezultatul următorului program, care compară direcțiile de rotunjire?

print(int(-2.7))print(-2.7 // 1)
  1. Prima linie -2, a doua linie -2.0
  2. Prima linie -3, a doua linie -3.0
  3. Prima linie -2, a doua linie -3.0
  4. Prima linie -3, a doua linie -2.0
Răspuns corectC. Prima linie -2, a doua linie -3.0

Funcția predefinită int() elimină partea zecimală, rotunjind spre 0, deci int(-2.7) nu este -3, ci -2. Pe de altă parte, // rotunjește spre podea, deci -2.7 // 1 tinde spre -3, iar cum unul dintre operanzi este float, rezultatul este de asemenea float, -3.0. Pentru numere pozitive, atât int(2.7), cât și 2.7 // 1, dau amândouă 2, deci diferența nu se vede, dar pentru numere negative direcțiile diferă. Niciuna dintre cele două nu este rotunjire obișnuită, deci pentru a obține -3 din -2.7 trebuie folosit round(-2.7).

Î15 | Eroarea de reprezentare zecimală

Care este rezultatul următorului program, care afișează două valori booleene pe 2 linii?

print(0.1 + 0.7 == 0.8)print(round(0.1 + 0.7, 2) == 0.8)
  1. Prima linie False, a doua linie False
  2. Prima linie True, a doua linie True
  3. Prima linie True, a doua linie False
  4. Prima linie False, a doua linie True
Răspuns corectD. Prima linie False, a doua linie True

float păstrează numerele zecimale în binar, deci valori simple în zecimal, precum 0.1 sau 0.7, nu pot fi reprezentate exact. De fapt, afișând 0.1 + 0.7 se obține 0.7999999999999999, ușor diferit de 0.8, deci prima linie este False. Pe a doua linie se compară după ce ambele valori au fost rotunjite la 2 zecimale cu round(), astfel încât ambele devin 0.8, iar rezultatul este True. Aceasta nu este o problemă specifică Python, ci o proprietate a numerelor în virgulă mobilă binară IEEE 754 — din același motiv, 0.1 + 0.2 devine 0.30000000000000004, iar 1.1 + 2.2 devine 3.3000000000000003. Se recomandă evitarea comparării directe a valorilor float pentru egalitate, în favoarea rotunjirii la un anumit număr de zecimale, a comparării diferenței absolute cu o toleranță, sau, în situații care cer precizie strictă precum sumele de bani, folosirea modulului decimal.

Î16 | Rotunjirea prin round

Care este rezultatul următorului program, care afișează pe o linie valorile rotunjite?

print(round(1.5), round(2.5), round(3.5))
  1. 2 2 4
  2. 2 3 4
  3. 1 3 3
  4. 1 2 3
Răspuns corectA. 2 2 4

round() din Python rotunjește spre cel mai apropiat număr par, așa-numita rotunjire bancară. Doar atunci când valoarea este exact la mijloc se alege parul cel mai apropiat, deci 1.5 devine 2, 2.5 devine 2, iar 3.5 devine 4, rezultatul fiind 2 2 4. Rotunjirea obișnuită, învățată la școală, ar da 2 3 4, dar Python nu folosește această convenție. 1 2 3 ar corespunde unei simple trunchieri a părții zecimale, iar 1 3 3 rotunjirii spre numărul impar — niciuna nu reflectă comportamentul real. De notat că round() fără al doilea argument returnează int, iar dacă se specifică numărul de zecimale, ca în round(2.5, 0), se returnează un float, 2.0.

Î17 | bool este int

Care este rezultatul următorului program, care tratează valori booleene ca numere?

print(True + True)print(isinstance(True, int))
  1. Prima linie True, a doua linie True
  2. Prima linie 2, a doua linie False
  3. Prima linie 2, a doua linie True
  4. Prima linie True, a doua linie False
Răspuns corectC. Prima linie 2, a doua linie True

bool este un tip care moștenește din int, deci True poate fi folosit direct ca întregul 1, iar False ca întregul 0, în operații numerice. True + True este 1 plus 1, adică 2, iar isinstance(True, int) returnează True. Dacă se citește prima linie ca True, înseamnă că + a fost confundat cu disjuncția logică — disjuncția în Python este or, iar True or True ar da True. Și issubclass(bool, int) este True, iar sum([True, False, True]) devine 2 din același motiv. Această proprietate este folosită frecvent pentru a număra câte elemente îndeplinesc o condiție.

Î18 | Precizia numerelor întregi

Care este descrierea corectă pentru tipul int din Python 3?

  1. Nu are limită de cifre și poate reprezenta valori oricât de mari, în limita memoriei disponibile
  2. Peste 32 de biți valoarea poate depăși capacitatea și deveni negativă
  3. Se produce OverflowError atunci când numărul de cifre depășește o limită
  4. Peste 64 de biți este convertit automat la float pentru calcul
Răspuns corectA. Nu are limită de cifre și poate reprezenta valori oricât de mari, în limita memoriei disponibile

int din Python 3 are precizie arbitrară, fără limită de cifre. 3 ** 40 se calculează exact ca 12157665459056928801, care depășește intervalul unui întreg semnat pe 64 de biți, dar tipul rămâne totuși int. Se pot manipula și valori precum 2 ** 1000, iar numărând cifrele cu len(str(2 ** 1000)) se obțin 302 cifre. Nefiind un întreg cu lungime fixă, ca în C, nu poate depăși capacitatea și deveni negativ, nici nu comută automat la float. OverflowError apare, de exemplu, atunci când o valoare depășește intervalul reprezentabil de float, nu doar pentru că numărul de cifre al unui int a crescut. Totuși, cu cât cifrele cresc, cu atât crește timpul de calcul și memoria folosită.

Î19 | Indexarea bytes

Care sunt rezultatele de pe linia 2 și linia 3 ale următorului program, care tratează un șir de octeți?

b = 'abc'.encode()print(b[0])print(b[0:1])
  1. Prima linie b'a', a doua linie b'a'
  2. Prima linie 97, a doua linie b'a'
  3. Prima linie 97, a doua linie 97
  4. Prima linie a, a doua linie b'a'
Răspuns corectB. Prima linie 97, a doua linie b'a'

Accesarea unui obiect bytes printr-un index întreg returnează valoarea octetului de la acea poziție, ca int. Primul octet din b'abc', rezultat prin codificarea 'abc' în UTF-8, este codul punctului 'a', deci 97. Pe de altă parte, extragerea printr-o felie (slice) returnează un obiect bytes de lungime 1, deci b[0:1] este b'a'. Pentru str, atât s[0], cât și s[0:1], dau același str, 'a', așa că aici se vede contrastul dintre str și bytes. Afișarea nu apare ca a, ci ca b'a', pentru că print() afișează bytes sub forma repr; pentru a reveni la un șir de caractere se folosește b.decode().

Î20 | Baze numerice și caractere

Care este rezultatul următorului program, care înșiruie conversii de bază numerică și de cod al caracterelor?

print(int('1010', 2), bin(10), hex(255), ord('A'))
  1. 10 0b1010 0xff 65
  2. 10 0b1010 0xFF 65
  3. 10 0b1010 0xff 97
  4. 1010 0b1010 0xff 65
Răspuns corectA. 10 0b1010 0xff 65

Al doilea argument al lui int() este baza numerică, deci int('1010', 2) citește șirul ca număr binar și returnează 10. A crede că rezultatul rămâne 1010 înseamnă a ignora specificarea bazei. bin() returnează un șir cu prefixul 0b, deci '0b1010', iar hex() returnează un șir cu litere mici și prefixul 0x, deci '0xff'. Nu se obține niciodată forma cu litere mari 0xFF; pentru a obține notația cu majuscule se folosește format(255, 'X'). ord() returnează codul punctului caracterului, iar pentru majuscula A este 65. 97 este codul punctului pentru minuscula a, iar conversia inversă, chr(65), redă 'A'.

Î21 | Felii (slice)

Care este rezultatul următorului program, care tratează felii dintr-un șir de caractere?

s = 'Pythonic'print(s[2:5])print(s[-3:])
  1. Prima linie tho, a doua linie nic
  2. Prima linie tho, a doua linie ic
  3. Prima linie thon, a doua linie nic
  4. Prima linie yth, a doua linie nic
Răspuns corectA. Prima linie tho, a doua linie nic

s[2:5] extrage începând de la indexul 2, până imediat înaintea indexului 5. Indexul 2 din 'Pythonic' este t, deci cele trei caractere t, h, o dau tho. Deoarece poziția finală nu este inclusă, rezultatul nu este thon. Dacă indexarea s-ar citi numărând de la 1, ca „al 2-lea caracter”, s-ar alege greșit yth, care corespunde de fapt lui s[1:4]. s[-3:] folosește un index negativ, numărând de la sfârșit, deci pornește de la al 3-lea caracter dinspre coadă, n, și merge până la final, dând nic. Dacă -3 s-ar interpreta greșit ca „până la al 3-lea caracter de la coadă”, s-ar alege ic, care corespunde de fapt lui s[-2:]. Reținând că indexarea începe de la 0 și că indexul negativ numără de la coadă, unde -1 este ultimul, nu mai apar confuzii.

Î22 | În afara intervalului și in

Care este rezultatul următorului program, care afișează două rezultate de verificare?

s = 'Python'print(s[100:200] == '')print('py' in s)
  1. Prima linie True, a doua linie False
  2. Prima linie True, a doua linie True
  3. Prima linie False, a doua linie True
  4. Prima linie False, a doua linie False
Răspuns corectA. Prima linie True, a doua linie False

O felie (slice) nu produce excepție chiar dacă intervalul depășește lungimea șirului — returnează doar partea suprapusă. 'Python' are doar 6 caractere, deci s[100:200] este un șir vid, iar comparația cu un șir vid dă True. Un index izolat, s[100], ar produce în schimb IndexError — aici este contrastul. Pe a doua linie, operatorul in verifică prezența unui subșir, dar face distincție între majuscule și minuscule, deci minuscula 'py' nu este conținută în 'Python', iar rezultatul este False. Cu 'Py' sau 'th' rezultatul ar fi True.

Î23 | Șirurile sunt imuabile

Ce se întâmplă dacă următorul program este scris într-un fișier și rulat?

s = 'abc's[0] = 'z'print(s)
  1. Se produce TypeError și atribuirea eșuează
  2. Se afișează zbc, cu litera înlocuită
  3. Se produce IndexError și atribuirea eșuează
  4. Se afișează abc, neschimbat
Răspuns corectA. Se produce TypeError și atribuirea eșuează

str este imuabil, adică nu poate fi modificat după creare, deci nu se poate rescrie un singur caracter prin index. s[0] = 'z' produce TypeError: 'str' object does not support item assignment, iar execuția se oprește acolo, deci nici print nu se mai execută. IndexError apare atunci când indexul este în afara intervalului, dar aici 0 este un index valid, deci nu este cazul. Pentru a schimba conținutul, trebuie creat un șir nou și reasamblat, de exemplu s = 'z' + s[1:]. Listele sunt mutabile, deci elementele lor pot fi rescrise în același mod.

Î24 | Valoarea returnată de metode

Care este rezultatul următorului program, care apelează metode ale șirurilor de caractere?

s = 'exam's.upper()print(s)print(s.replace('e', 'E'))
  1. Prima linie EXAM, a doua linie Exam
  2. Prima linie EXAM, a doua linie EXAM
  3. Prima linie exam, a doua linie exam
  4. Prima linie exam, a doua linie Exam
Răspuns corectD. Prima linie exam, a doua linie Exam

Metodele șirurilor de caractere nu modifică șirul original, ci creează și returnează un șir nou. s.upper() de pe a doua linie creează 'EXAM', dar cum rezultatul nu este atribuit nicăieri, valoarea este pierdută, iar s rămâne 'exam'. Prin urmare, print(s) afișează exam. Pe linia a 4-a se afișează direct valoarea returnată de s.replace('e', 'E'), deci apare Exam, dar nici aceasta nu modifică s însuși. Pentru a păstra rezultatul, trebuie reatribuit, ca în s = s.upper(). Este un contrast cu metode precum sort() de la liste, care rearanjează pe loc și returnează None.

Î25 | f-string

Care este rezultatul următorului program, care afișează cu format specificat?

n = 2.71828print(f'{n:.2f}')print(f'{"ok"!r}')
  1. Prima linie 2.71, a doua linie 'ok'
  2. Prima linie 2.72, a doua linie ok
  3. Prima linie 2.718, a doua linie ok
  4. Prima linie 2.72, a doua linie 'ok'
Răspuns corectD. Prima linie 2.72, a doua linie 'ok'

Specificatorul de format :.2f dintr-un f-string afișează rotunjit la 2 zecimale, deci 2.71828 devine 2.72. Nu este trunchiere, deci nu devine 2.71; 2.718 ar fi valoarea obținută cu :.3f. Pe a doua linie, !r este un specificator de conversie care afișează valoarea în forma repr(). Aplicat unui șir de caractere, adaugă ghilimele, deci rezultă 'ok'; fără !r ar apărea doar ok. Sintaxa specificatorilor de format este comună cu str.format(), deci și '{n:.2f}'.format(n=2.71828) ar da același rezultat, 2.72.

Î26 | split

Care este rezultatul următorului program, care împarte un șir de caractere?

print('a b  c'.split())print('a,b,c'.split(',', 1))
  1. ['a', 'b', 'c'] și ['a', 'b', 'c']
  2. ['a', 'b', '', 'c'] și ['a', 'b,c']
  3. ['a', 'b', 'c'] și ['a', 'b,c']
  4. ['a', 'b', '', 'c'] și ['a', 'b', 'c']
Răspuns corectC. ['a', 'b', 'c'] și ['a', 'b,c']

Când split() este apelat fără argumente, tratează spațiile consecutive ca un singur separator, fără să creeze elemente vide. De aceea, 'a b c'.split() dă lista cu 3 elemente ['a', 'b', 'c']. Dacă separatorul este specificat explicit, ca în 'a b c'.split(' '), tăierea se face la fiecare spațiu în parte, deci rămâne un șir vid și rezultă cele 4 elemente ['a', 'b', '', 'c']. Al doilea argument este maxsplit, care limitează numărul de tăieri; pasând 1, se taie o singură dată, la prima apariție, rezultând ['a', 'b,c'], iar restul rămâne grupat într-un singur element. Dacă este omis, se taie complet, rezultând ['a', 'b', 'c'].

Î27 | strip

Care este rezultatul următorului program, care elimină caractere de la ambele capete?

print('xxabxx'.strip('x'))print('xxabxx'.lstrip('x'))
  1. Prima linie abxx, a doua linie ab
  2. Prima linie ab, a doua linie abxx
  3. Prima linie xabx, a doua linie abxx
  4. Prima linie ab, a doua linie xxab
Răspuns corectB. Prima linie ab, a doua linie abxx

Argumentul lui strip() este „mulțimea caracterelor de eliminat” și continuă să elimine, de la ambele capete, orice caracter din acea mulțime, atâta timp cât se succed. Nu elimină doar un singur 'x' ca subșir, deci 'xxabxx'.strip('x') elimină toate literele x de la ambele capete, dând ab. Dacă s-ar crede că se elimină un singur caracter de fiecare parte, s-ar alege greșit xabx. lstrip() acționează doar la capătul stâng, dând abxx, iar rstrip() doar la capătul drept, dând xxab. Dacă argumentul e omis, se elimină spațiile albe. Fiind tratat ca mulțime, 'xxabxx'.strip('xa') ar elimina și xx-ul din stânga, și a, rămânând doar b.

Î28 | join și repetare

Care este rezultatul următorului program, care unește șiruri de caractere?

print('-'.join('abc'))print('ab' * 3)
  1. Prima linie -a-b-c-, a doua linie ababab
  2. Prima linie abc, a doua linie ababab
  3. Prima linie a-b-c, a doua linie ab ab ab
  4. Prima linie a-b-c, a doua linie ababab
Răspuns corectD. Prima linie a-b-c, a doua linie ababab

join() folosește șirul apelant ca separator și unește elementele obiectului iterabil primit. Și un șir de caractere este un obiect iterabil, ale cărui caractere pot fi extrase unul câte unul, deci '-'.join('abc') unește 'a', 'b' și 'c' cu cratimă, rezultând a-b-c. Separatorul apare doar între elemente, nu la început sau sfârșit, deci nu rezultă -a-b-c-. Rezultatul fără separator, abc, s-ar obține din ''.join('abc'). Operatorul * repetă un șir de un număr specificat de ori, deci 'ab' * 3 devine ababab, fără spații între repetiții. Pentru a obține ab ab ab, ar trebui scris ' '.join(['ab'] * 3).

Î29 | find și index

Care este rezultatul următorului program, care caută un subșir?

print('banana'.find('z'))print('banana'.index('n'))
  1. Prima linie -1, a doua linie 2
  2. Prima linie -1, a doua linie 3
  3. Prima linie -1, a doua linie 4
  4. Prima linie 0, a doua linie 2
Răspuns corectA. Prima linie -1, a doua linie 2

find() returnează -1 atunci când nu găsește subșirul, fără a produce excepție. 'banana' nu conține 'z', deci rezultatul este -1. 0 ar fi valoarea obținută dacă subșirul e găsit chiar la început, așa că nu trebuie confundat cu cazul negăsirii. index() este similar lui find() în privința returnării poziției, iar prima apariție a lui 'n' în 'banana' este la indexul 2, deci rezultatul este 2. 3 ar corespunde numărării indexului de la 1, ca „al 3-lea caracter”, iar 4 este poziția ultimei apariții — pentru aceasta se folosesc rfind() sau rindex(). Diferența dintre cele două apare doar când nu se găsește nimic: index() produce ValueError: substring not found și oprește execuția.

Î30 | Șirul raw

Care este rezultatul următorului program, care numără caracterele?

print(len(r'a\nb'), len('a\nb'))
  1. 3 4
  2. 4 4
  3. 3 3
  4. 4 3
Răspuns corectD. 4 3

Într-un șir raw, precedat de r, bara oblică inversă nu mai este interpretată ca început de secvență de escape. r'a\nb' conține cele 4 caractere a, bară oblică inversă, n, b, deci len este 4. În schimb, în șirul obișnuit 'a\nb', \n este înlocuit cu un singur caracter de linie nouă, deci rezultă cele 3 caractere a, linie nouă, b, iar len este 3. Numărând ambele ca secvențe de escape, ar rezulta 3 3, iar numărând ambele ca fiind caractere brute, ar rezulta 4 4, dar esențial este că tratamentul diferă în funcție de prezența lui r. Chiar și cu r, tipul rămâne str obișnuit, nu devine un tip special. De notat că len('\\') este 1, deoarece bara oblică inversă se scrie dublată pentru a reprezenta un singur caracter.

Exersare: rezolvați întrebările de pe această pagină

Acesta este un instrument de exersare cu întrebări în ordine aleatorie (funcționează când JavaScript este activat). Puteți citi oricum toate întrebările și explicațiile de mai sus.

* Explicațiile sunt informații în scop de studiu. Tematica și sistemul examenelor se schimbă de la an la an, așa că verificați întotdeauna anunțurile oficiale ale organizatorului examenului.

Această pagină este o traducere a textului original în japoneză. Dacă traducerea diferă de original, prevalează versiunea în japoneză. Vedeți originalul în japoneză