Vodič za Pajton 2.6/Više sa listama
Već smo videli liste i kako se mogu koristiti. Sada kada imate malo više predzanja ići ću u više detalja o listama. Prvo ćemo pogledati više načina da se dobiju elementi u listi, a onda ćemo pričati o kopiranju.
Evo nekih primera korišćenja pristupa indeksiranja jednom elementu liste:
>>> неки_бројеви = ['нула', 'један', 'два', 'три', 'четири', 'пет'] >>> неки_бројеви[0] 'нула' >>> неки_бројеви[4] 'четири' >>> неки_бројеви[5] 'пет'
Svi ovi primeri treba da izgledaju poznato. Ako želite prvu stavku u listi samo pogledajte indeks 0. Druga stavka je indeks 1 i tako dalje kroz listu. Međutim šta ako želite poslednju stavku u listi? Jedan način bi bio korišćenje len()
funkcije kao неки_бројеви[len(неки_бројеви) - 1]
. Ovaj način radi pošto len()
funkcija uvek vraća poslednji indeks plus jedan. drugi bi onda bio неки_бројеви[len(неки_бројеви) - 2]
. Postoji lakši način da se ovo uradi. U Pajtonu poslednja stavka je uvek indeks -1. Pretposlednji je indeks -2 and i tako dalje. Evo još nekih primera:
>>> неки_бројеви[len(неки_бројеви) - 1] 'пет' >>> неки_бројеви[len(неки_бројеви) - 2] 'четири' >>> неки_бројеви[-1] 'пет' >>> неки_бројеви[-2] 'четири' >>> неки_бројеви[-6] 'нула'
Tako svaka stavka u listi može biti indeksirana na dva načina: spreda i otpozadi.
Drugi koristan način da se u delovima liste koristi odsecanje. Evo još jednog primera koji će Vam dati ideju za šta može da se koristi:
>>> ствари = [0, 'Фред', 2, 'С.П.А.М.', 'Чарапа', 42, "Џек", "Џил"] >>> ствари[0] 0 >>> ствари[7] 'Џил' >>> ствари[0:8] [0, 'Фред', 2, 'С.П.А.М.', 'Чарапа', 42, 'Џек', 'Џил'] >>> ствари[2:4] [2, 'С.П.А.М.'] >>> ствари[4:7] ['Чарапа', 42, 'Џек'] >>> ствари[1:5] ['Фред', 2, 'С.П.А.М.', 'Чарапа']
Presecanje se koristi da se vrati deo liste. Operator odsecanje je u obliku ствари[први_индекс:последњи_индекс]
. Odsecanje seče listu posle први_индекс
i pre последњи_индекс
i vraća delove između. Možete koristiti oba tipa indeksiranja:
>>> ствари[-4:-2] ['Чарапа', 42] >>> ствари[-4] 'Чарапа' >>> ствари[-4:6] ['Чарапа', 42]
Drugi trik je sa osecanjem neodređenog indeksa. Ako prvi indeks nije određen početak liste se pretpostavlja. Ako poslednji indeks nije naveden ceo ostatak liste se pretpostavlja. Ovde su neki primeri:
>>> ствари[:2] [0, 'Фред'] >>> ствари[-2:] ['Џек', 'Џил'] >>> ствари[:3] [0, 'Фред', 2] >>> ствари[:-5] [0, 'Фред', 2]
Ovde je (HTML-om inspirisan) primer programa (kopirate u pesmi definicije ako želite):
песма = ["<B>", "Џек", "и", "Џил", "</B>", "су", "отишли", "уз",
"брдо", "да", "<B>", "донесу", "кофу", "</B>",
"воде.", "Џек", "је пао", "<B>", "доле", "и", "разбио",
"</B>", "његову", "круницу", "и", "<B>", "Џил", "се",
"</B>", "преврнула", "после"]
def започни_затамњено(текст):
true = 1
false = 0
## затамњено говори да ли тренутно гледамо или не
## затамњени део текста.
затамњено = false
## почетак_блок је индекс почетка неког незатмњеног
## дела текста или затамњеног.
почетак_блок = 0
for идекс in range(len(текст)):
## Рукује са покретањем затамњеног текста
if текст[индекс] == "<B>":
if затамњено:
print "Грешка: Додатно затамњено"
## print "Није затамњено:", тектс[почетак_блок:индекс]
затамњено = true
почетак_блок = индекс + 1
## Рукује крајем затамњених слова
## Не заборавите да је последњи број у делу индекс
## након што је последњи индекс коришћен.
if текст[индекс] == "</B>":
if not затамњено:
print "Грешка: сувише близу затамњеног"
print "Затамњено[", почетак_блок, ":", индекс, "]", текст[почетак_блок:индекс]
затамњено = false
почетак_блок = индекс + 1
започни_затамњено(песма)
sa izlazom:
Затамњено [ 1 : 4 ] ['Џек', 'и', 'Џил'] Затамњено [ 11 : 15 ] ['да', 'донесу', 'кофу'] Затамњено [ 20 : 23 ] ['доле', 'и', 'разбио'] Затамњено [ 28 : 30 ] ['Џил', 'се']
Funkcija започни_затамњено()
traži u listi koja je podeljena na reči
i znakove. Znaci koje traži su <B>
gde počinje
zatamnjeni tekst i </B>
gde se završava. Funkcija
започни_затамњено()
ide kroz kod i taži početak i kraj
znakova.
Sledeći karakteristika sa listama je kopiranje. Ako pokušate nešto jednostavno kao:
>>> a = [1, 2, 3] >>> b = a >>> print b [1, 2, 3] >>> b[1] = 10 >>> print b [1, 10, 3] >>> print a [1, 10, 3]
Ovo verovatno izgleda iznenađujuće s obzirom da je dobro došlo do izmene b
rezultata u a
. Ono što se događa je da
naredba b = a
pravi b
kao referencu od a
.
Ovo znači da se b
može posmatrati kao drugo ime za a
.
Stoga svaka modifikacija b
menja a
isto tako. Međutim,
neki zadaci ne stvaraju dva imena za jednoj listi:
>>> a = [1, 2, 3] >>> b = a * 2 >>> print a [1, 2, 3] >>> print b [1, 2, 3, 1, 2, 3] >>> a[1] = 10 >>> print a [1, 10, 3] >>> print b [1, 2, 3, 1, 2, 3]
U ovom slučaju b
nije referenca od a
pošto
izraz a * 2
stvara novu listu. Zatim naredba
b = a * 2
daje b
referencu za a * 2
pre nego
referencu za a
. Sve dodele operacija prave referencu.
Kada prođete listu kao argument funkcije stvorili ste
dobro reference. Većinu vremena ne morate da brinete o
stvaranju referenci umesto kopija. Međutim, kada treba da se
promeni jedna lista bez promene drugog imena liste
treba da se uverite da ste stvarno stvorili kopiju.
Postoji nekoliko načina da napravite kopiju liste. Najjednostavniji koji uglavnom radi da operator odseca jer to uvek pravi novu listu čak iako je taj deo cela lista:
>>> a = [1, 2, 3] >>> b = a[:] >>> b[1] = 10 >>> print a [1, 2, 3] >>> print b [1, 10, 3]
Uzimanjem dela [:]
stvara se nova kopija liste. Međutim to
kopira samo spoljašnju listu. Bilo koja podlista unutra je i dalje referenca
podliste u originalnoj listi. Stoga, kada lista
sadrži liste, unutrašnje liste moraju biti dobro kopirane. Možete to
uraditi ručno ali Pajton već sadrži režim za to. Bi samo
koristite deepcopy
funkciju iz copy
režima:
>>> import copy >>> a = [[1, 2, 3], [4, 5, 6]] >>> b = a[:] >>> c = copy.deepcopy(a) >>> b[0][1] = 10 >>> c[1][1] = 12 >>> print a [[1, 10, 3], [4, 5, 6]] >>> print b [[1, 10, 3], [4, 5, 6]] >>> print c [[1, 2, 3], [4, 12, 6]]
Pre svega primetite da je a
lista liste. Zatim
da kada se b[0][1] = 10
porenu oba a
i b
su
promenjeni, ali c
nije. Ovo se dešava zato što su unutrašnji nizovi
i dalje reference kada se koristi operator odsecanja. Međutim sa
deepcopy
c
je potpuno iskopirano.
Pa, da li treba da brinem o ovim referencama svaki put kada koristim
funkciju ili =
? Dobra vest je da samo morate da brinete o
referencama kada koristite rečnike i liste. Brojevi i nizovi
stvaraju reference kada se dodeljuje ali svaka operacija nad brojevima i
nizovima,koja ih menja, stvara novu kopiju pa ih nikada ne možete promeniti
neočekivano. Vi morate da mislite o referencama samo kada menjate
listu ili rečnik.
Do sada ste se verovatno zapitali zašto se uopšte koriste reference? Osnovni razlog je brzina. Mnogo je brže napraviti referencu za hiljadu elemenata liste nego da kopirate svaki element liste. Drugi razlog je je taj što Vam dozvoljava da imate funkciju za menjanje unete liste ili rečnika. Samo zapamtite za reference, ako ikad imate neki čudan problem sa izmenjenim podatkom koji ne bi trebalo da bude takav.