Introducere in Python

 

Cuprins

1.      Primii pasi in Python

2.      Ce este Python?

3.      Unde se gaseste?

4.      Cum se ruleaza un program Python?

5.      Cateva precizari inainte de a scrie primul program

6.      Tipuri de date si variabile

7.      Stringuri

8.      Liste si Tupluri

9.      Dictionare

10.  Structuri conditionale

11.  Structuri repetitive

12.  Functii

13.  Includerea de cod extern

14.  Clase si obiecte

15.  Exceptii

16.  Alte particularitati Python

17.  Exemple de programe rezolvate

18.  Exercitii propuse

19.  Resurse

 

Primii pasi in Python

Python este un limbaj de scripting de nivel inalt. Vom prezenta in continuare primii pasi care trebuie facuti pentru a scrie un program Python, cateva exemple si unele ponturi care sa va ajute in depasirea problemelor de inceput.

 

Ce este Python?

Python este un limbaj de programare care castiga tot mai multa popularitate, fiind comparat uneori cu Perl. Ce este de fapt Python? Este un limbaj de scripting, ceea ce inseamna ca este interpretat si nu compilat, economisind mult timp in procesul de dezvoltare si depanare.

Python este un limbaj de nivel inalt - permite scrierea de programe complexe mult mai rapid si usor decat in limbaje de genul C sau C++.

Limbajul combina o putere remarcabila cu o sintaxa foarte clara. Are module, clase, exceptii si tipuri dinamice de nivel inalt. Ofera interfete la multe apeluri sistem si librarii, precum si la diverse sisteme de ferestre (X11, Motif, Tk, Mac, MFC).

Implementarea Python este portabila: ruleaza pe Linux, Unix, Windows, OS/2, Mac OS X, Amiga si chiar pe unele telefoane mobile de la Nokia. Python a fost portat, de asemenea, pe masinile virtuale Java si .NET.

 

Unde se gaseste?

Python se poate downloada de pe site-ul oficial, sectiunea Download.

Pe un system Linux, e posibil sa fie deja instalat. Verificati asta dintr-o consola:

$ python
Python 2.3.4 (#2, Sep 24 2004, 08:39:09)
[GCC 3.3.4 (Debian 1:3.3.4-12)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

Daca nu il aveti instalat, pasul urmator ar fi sa-l cautati pe CD-urile distributiei de Linux cu care lucrati. O alternativa ar fi folosirea serviciului apt-get de pe o distributie Debian (sau yum pentru RedHat).

apt-get install python

Sau il puteti descarca, apoi compila si instala manual:

./configure
make
make install

Pe un system Windows se poate downloada de la Download fisierul Python 2.5.2 Windows installer (versiunea 2.5.2 incepand cu 22 Feb 2008). Se ruleaza fisierul: python-2.5.2.msi (apoi se urmeaza pasii de instalare). Dupa instalare se poate adauga calea catre executabilul python in global PATH, pentru a putea fi gasit de oriunde: “Control Panel” -> “System” ->[in plus pt Windows Vista: -> “Advanced System Settings” in partea superioara stanga] -> Tabul “Advanced” -> “Environment Variables” -> In zona de “System Variables” se cauta variabila “path” in lista, se da “Edit” ->se adauga la sfarsitul randului “Variable value” caracterul “;” urmat de calea catre executabilul “python.exe” (de ex, se adauga:  “;c:\Python25”, fara ghilimele) -> 3xOK.

 

Cum se ruleaza un program Python?

In Windows, daca extensia .py este deja inregistrata, un dublu-clik pe numele scriptului este suficient. Se poate edita programul folosind IDLE (Python GUI) si apasand tasta F5 pentru rulare sau se poate executa din consola (Start->Run->cmd).

Daca folositi Linux, exista mai multe posibilitati:

$ cat hello.py

print 'Hello World!'

$ python hello.py

Hello World!

$ cat hello.py

#!/usr/bin/python

print 'Hello World!'

$ chmod +x hello.py

$ ./hello.py

Hello World!

 

Cateva precizari inainte de a scrie primul program

Python este un limbaj interpretat. In Python, o linie noua termina o declaratie; pentru a continua o declaratie pe mai multe linii, se foloseste caracterul  ”\”.

In Python pe langa liniile noi, indentarea este mai mult decat parte a stilului de programare, este chiar parte din sintaxa (identarea se refera la spatiile/distanta intre inceputul unui rand si primul cuvant). Un bloc de cod are toate liniile identate cu acelasi numar de spatii (nu exista begin si end sau {} ca in C). Instructiunile dintr-un bloc de cod vor fi grupate unele sub altele, pe acelasi nivel de identare. Structurile de control, definirea de rutine, clase, toate necesita o mai mare grija in scrierea codului. Exemplu de folosire a identarii pentru a delimita blocurile de cod :

a = 1

"""

Afisam numerele de la 1 la 10

"""

while a <= 10:

print a,

a += 1

#b = 1

b = 2

print "Am terminat"

Definitiile neindentate intr-un program Python vor fi de obicei variabile globale, definitii de clase, proceduri, functii sau parti ale "programului principal".

Dupa cum se observa si din exemplul de mai sus, dupa instructiuni nu se pune simbolul ";" precum in alte limbaje de programare, indentarea corespunzatoare fiind suficienta.

Este foarte important sa nu uitati simbolul ":" care precede de obicei o indentare, deoarece omiterea sa poate sa fie cauza multor erori, cel putin la inceput.

O singura linie se poate comenta in Python folosind simbolul "#". Pentru comentarii multiline se folosesc trei ghilimele succesive """ (sau ''') la inceputul si respectiv la sfarsitul zonei de comentat.

 

Tipuri de date si variabile

In Python se poate lucra cu numere intregi si numere in virgula mobila. Numerele intregi dintr-o expresie se convertesc automat in numere in virgula mobila daca este necesar.

Numele de variabile si functii sunt case-sensitive. La definirea variabilelor nu trebuie precizat tipul acestora. Python asociaza numele unei variabile cu un obiect, care poate fi numar, string sau ceva mai complex. Cand este folosita o variabila, tipul acesteia este tipul obiectului cu care este asociata. Este gresita folosirea intr-o expresie a unei variabile care nu a fost asociata cu un obiect. Astfel, daca se scrie:

i = 5

i va fi de tip intreg. Daca se scrie:

i = "Hello"

 

i va fi de tip string.

 

Python nu face conversie automata intre tipurile string si integer. Pentru acest lucru se folosesc funtiile int(some_string) pentru transfomarea din string in integer si respectiv: str(some_int) sau repr(some_int) sau `some_int` (caracterul de pe tasta cu ~) pentru transfomarea din integer in string. Se poate folosi si scrierea formatata folosind structura '[string]%type[string] ' % (var_name).  Atentie! In cazul transformarii din string in integer, daca stringul ce trebuie convertit contine si alte caractere decat cifre, la rulare va aparea o eroare: ValueError: invalid literal for int() with base 10. De exemplu, rularea instructiunilor:

i = "1"

j = "2"

a = 1

b = 2

print "Un string:", i+j

print "Un numar:", int(i)+int(j)

print "Un string", str(a)+str(b)

print "Afisare formatata:", 'persoana %s are %d ani' % (j, a)

va afisa:

Un string: 12

Un numar: 3

Un string 12

Afisare formatata: persoana 2 are 1 ani

Alocarea si dealocarea de memorie se face automat de catre Python.

In Python se poate lucra direct cu numere complexe, folosind sintaxa: a+bj unde a = partea reala si b = partea imaginara. De exemplu, rularea instructiunii:

print (2.0+3.0j)*(2.1-6.0j)

va afisa:

(22.2-5.7j)

In Python se poate face atribuirea de valori la mai multe variabile simultan:

x, y = 2, 3

Datorita faptului ca partea dreapta a unei expresii este evaluata inainte de a se face atribuirea, valorile a doua variabile pot fi foarte usor interschimbate, fara a avea nevoie de o a treia variabila:

x, y = y, x

In Python, se folosesc simbolurile aritmetice standard, cu % pentru operatia modulo.

 

Stringuri

Stringurile sunt incluse intre ghilimele " (sau '). Stringurile ce contin mai multe linii sunt inconjurate de trei ghilimele succesive """ (sau ''').

s = "string"

linie = """text

pe mai multe linii"""

Stringurile sunt tratate ca vectori, cuvant[i] fiind caracterul din sir ce are indexul i; i ia valori in intervalul [-length,length). Folosirea unei valori in afara acestui interval va genera o eroare (IndexError: string index out of range). Nu exista un tip de date special pentru a defini un caracter (acesta e vazut ca un sir de lungime 1). Lungimea unui string se poate afla cu ajutorul functiei: len(some_string).

stringul:         s   t   r   i   n   g

index:            0   1   2   3   4   5

index negativ:   -6  -5  -4  -3  -2  -1

Caracterul ”:” specifica un substring al unui sir folosing sintaxa: some_string[x:y]. Substringul obtinut contine toate caracterele din sirul initial (some_string) intre pozitiile x si y-1 (inclusiv). Daca nu se specifica x sau y, acestea au implicit valorile 0, respectiv lungimea sirului.

Nu se pot modifica caracterele unui sir folosind adresarea cu indici in atribuire (NU se poate face de exemplu: s[1] = "x").

Sirurile de caractere pot fi concatenate folosind simbolul ”+” si pot fi multiplicate folosind caracterul ”*”. De exemplu, rularea instructiunilor:

s = "string"

print s[0:2]

print s[:3]

print s[3:]

s2 = "one"

print "Write " + 2*s2 + " " + s

va afisa:

st

str

ing

Write oneone string

Mai multe detalii despre metode de stringuri se pot gasi [aici].

Liste si Tupluri

Python pune la dispozitie doua tipuri de structuri pentru a grupa mai multe elemente : tupluri si liste. Diferenta principala dintre cele doua tipuri este ca tuplul nu mai poate fi modificat dupa ce a fost declarat.

Lista se declara folosind paranteze drepte.

Tuplul se declara folosind paranteze rotunde.

Elementele unei liste sau ale unui tuplu pot fi de tipuri diferite.

lista = ["string", 10]

tuplu = ("string", 10)

 

Accesarea elementelor unei liste sau unui tuplu se face la fel ca in cazul sirurilor de caractere, cu indecsi pozitivi, negativi sau folosing operatorul ”:” .

Spre deosebire de stringuri elementele unei liste pot si modificate cu ajutorul accesarii prin indecsi. Se pot adauga elemente intr-o lista folosind functia append() si se pot combina doua liste folosind functia extend().

lista.append(5)

lista.extend(alta_lista)

Elementele unei liste se pot sterge folosindu-se del.

del lista[2]

del lista[0:2]

O noua lista poate fi creata din alta lista folosind ”list comprehensions” (o expresie urmata de o clauza for, apoi de 0 sau mai multe clauze for sau if. De exemplu, rularea instructiunilor:

lista_veche = [1,2,3,4]

lista = [ elem*2 for elem in lista_veche if elem!= 3]

print lista

print [(x, x**2) for x in lista_veche]

va afisa:

[2, 4, 8]

[(1, 1), (2, 4), (3, 9), (4, 16)]

 

In expresia de mai sus, if este optional.
Numarul de elemente dintr-o lista sau un tuplu se poate afla folosind functia len().

Elementele unui tuplu nu mai pot fi modificate dupa ce au fost declarate. Din acest motiv nici o functie prezentata mai sus ce modifica elementele unei liste nu poate fi aplicata asupra tuplurilor.

 

Dictionare

O structura dictionar este un set neordonat de chei si valori in care valoarea poate fi cautata folosindu-se cheia. Cheile sunt de obicei numere intregi sau stringuri. Ele pot sa fie in orice ordine si pot sa nu fie de acelasi tip.

dict[0] = "primul"

dict["unu"] = 2

Pentru a acesa un element al unui dictionar se procedeaza in felul urmator:

var = dict[0]

sau

var = dict["unu"]

Dictionarele sunt declarate folosind acolade, elementele sunt de forma cheie:valoare despartite de virgule.

dict = {0: "primul" , "unu":2}

Se poate afla dimensiunea unui dictionar folosindu-se functia len() (cu sintaxa: len(some_dict) ) si se poate sterge o intrare din dictionar folosindu-se del (cu sintaxa: del some_dict[index]).

In plus se poate verifica daca exista o valoare pentru o cheie data. Pentru o versiune Python mai veche de 2.2. se foloseste functia  has_key a obiectului dictionar. O data cu versiunea 2.2. exista operatorul in care inlocuieste functia de mai sus.

if  mykey in dict:

      [code]

Functia keys() a obiectului dictionar returneaza o lista ce contine toate cheile din dictionar.

 

Structuri conditionale

if conditie1:

      instructiuni

elif conditie2:

      instructiuni

else:

      instructiuni

 

Pot exista mai multe sectiuni elif sau nici una iar sectiunea else apare o data sau niciodata.

Numarul 0, liste si tupluri goale, stringuri vide si valoarea None sunt considerate false daca sunt folosite  in evaluarea unei conditii.

 

Structuri repetitive

Instructiunea for functioneaza dupa elementele unei secvente(string, lista sau tuplu).

 

for el in lista:

      [instrutiuni]

 

Operatorul range() construieste o lista cu elemente in progresie aritmetica. Are urmatoarea sintaxa: range(x[,y[,pas]]) - formeaza o lista cu elemente mai mici ca y in progresie aritmetica, cu ratia pas. Primul element al listei este x. Implicit x este 0 si ratia este 1.

 

for i in range( len(s)):

      print s[i]

 

Instructiunea while continua iteratia cat timp conditia specificata este adevarata.

while conditie:

      [instructiuni]

 

Instructiunea break termina fortat orice bucla while sau for, iar instructiunea continue sare la urmatoarea iteratie.

Instructiunile while si for pot avea o clauza else. Aceasta se executa cand se termina lista dupa care se face iteratia for sau atunci cand conditia while a devenit false. Instructiunile din clauza else nu se executa in cazul in care bucla este terminata printr-o instructiune break.

while conditie:

      [instructiuni]

else:

      [instructiuni]

 

Functii

Functile sunt definite folosind cuvantul def. Rularea instructiunilor:

 

def fractie(x,y):

      if (y==0):

            return

      else:

            return float(x)/float( y)

print fractie(6,4)

 

va afisa:

1.5

 

Se specifica doar numele argumentelor, tipul lor fiind cel trimis la apelarea functiei.

Pentru a accesa variabilele globale ale programului, trebuie sa folosim cuvantul-cheie "global" cu sintaxa: global some_var.

Prima instructiune din corpul unei functii poate fi un sir de caractere, acest sir fiind documentatia functiei.

Functiile care se termina fara sa foloseasca instructiunea return sau care executa return fara argumente, intorc o valoare None.

Se pot specifica valori implicite pentru parametrii unei functii.

def fractie(x, y=1):

 

La apelare se pot specifica doua valori sau doar una. Daca functia se apeleaza cu doua valori nu se tine cont de valoarea implicita a lui y, daca se apeleaza cu o valoare (de ex fractie(4) ), x va lua valoarea 4, iar y valoarea implicita 1.

Functiile mai pot fi apelate folosind, in loc de argumente, cuvinte cheie de forma: cuvant_cheie = valoare. Pentru exemplul de mai sus se poate mai apela functia si astfel :

fractie(y=7, x=5)

fractie(6,y=1)

 

Daca o functie are un parametru de tipul *lista, atunci la apelare functia va primi o lista de argumente. Rularea instructiunilor:

def suma(*lista):

      s=0

      for i in lista:

            s=s+i

      return s

      print suma(2,3,5)

 

va afisa:

10 # adica 2+3+5

 

Daca o functie are un parametru de tipul **nume, atunci la apelare functia va primi o lista de cuvinte cheie de forma cuv_cheie = valoare. Rularea instructiunilor:

def afisare(**nume):

      for i in nume.keys():

            print i,':',nume[i]

va afisa:

client : Alex

vanzator : Alina

 

Includerea de cod extern

In Python se pot include in alte programe functii scrise in alt fisier. Un astfel de fisier ce poate fi importat poarta denumirea de modul. Exemplu:

import random

 

Instructiunea import din exemplul de mai sus nu incarca in tabela de simboluri numele functiilor definite in modulul random, ci doar numele modulului. Folosind acest nume se pot accesa functii definite in interiorul modulului folosindu-se sintaxa nume_modul.nume_functie(parametri).

random.random()

 

Clase si obiecte

Trebuie subliniat ca in Python, cuvantul "obiect" nu se refera neaparat la instantierea unei clase. Clasele in sine sunt obiecte, iar, in sens mai larg, in Python toate tipurile de date sunt obiecte. Exista tipuri de date care nu sunt clase: numerele intregi, listele, fisierele. Toate tipurile de date insa au aproximativ acelasi comportament, mai usor de explicat daca ne referim la aceste tipuri de date folosind cuvantul "obiect".

Un obiect se creaza in Python prin folosirea cuvantului cheie class:

class className [(super_class1 [, super_class2]*)]:

[Suite]

Creaza un obiect de tip clasa si ii da numele className. Suite poate contine definitii de metode locale si atribuiri pentru variabile locale. Clasa este derivata din super_class1 si din super_class2.

class MyClass (object): ...

Creaza o clasa de tip "new-style" prin mostenire din object. Vechiul tip de clase nu mostenesc object.

In lucrul cu clase, trebuie stiute urmatoarele reguli:

class Complex:

def __init__(self, realpart, imagpart):

self.r = realpart

self.i = imagpart

x = Complex( 3.0, -4.5)

De multe ori vom implementa clase derivand din clasa Thread, caz in care ar trebui respectate urmatoarele reguli:

Exceptii

Unele apeluri de functii pot arunca exceptii care trebuie prinse. In Python exista mecanismul try-except, asemanator celui try-catch din Java.

try:

      x = int(buffer)

except(ValueError):

      print "Date de intrare invalide"

Mecanismul functioneaza in felul urmator: se executa instructiunile din blocul try. Daca apare o exceptie tratata de un bloc except, executia sare la instructiunile din blocul repectiv. Dupa ce exceptia este tratata, executia continua cu prima instructiune din blocul try. Daca apare o exceptie ce nu este tratata de nici un bloc except, aceasta este propagata ascendent in alte blocuri try si primeste denumirea de excetie netratata (unhandled exception).

O exceptie poate fi aruncata folosind instructiunea raise. Aceasta poate fi folosita si fara argumente in interiorul unui bloc except pentru a re-arunca exceptia prinsa de blocul respectiv.

if (j>100):

      raise ValueError,j

O instructiune try poate avea mai multe clauze except. Ultima clauza except poate sa nu aiba specificata nici o exceptie de tratat fiid astfel folosita pentru a trata toate exceptiile netratate de celelalte clauze.

Instructiunile try pot avea optional si o clauza else. Instructiunile din blocul else sunt executate atunci cand blocul try nu genereaza nici o exceptie.

 

Alte particularitati Python

Generarea de numere pseudo-aleatoare se face la fel de usor ca in alte limbaje. Se importa modulul random (import random), se seteaza eventual seed-ul folosind random.seed, iar random.randint(a,b) spre exemplu va intoarce un intreg cuprins in intervalul inchis [a,b].

Lucrul cu liste este foarte comod in Python. Listele pot fi folosite si sub forma de stiva sau coada prin intermediul functiilor puse la dispozitie (append() si pop() ). Afisarea unei liste se poate face folosind un simplu print lista.

O lista se initializeaza la fel de simplu:

lista = []

Putem referi o sublista a unei liste, ajutandu-ne de doi indecsi:

sublista = lista[index1:index2]

Indexarea se face de la zero. Mai sus, se vor intoarce elementele listei initiale de la index1 la index2-1. Astfel, lista[n: (n+1)] va intoarce o lista care contine un singur element, cel de pe pozitia n, iar lista[n:n] va intoarce [].

In plus, exista o suita de functii foarte utile pentru obiectele de tip lista. Cele mai folosite sunt:

Unele apeluri de functii pot arunca exceptii care trebuie prinse. Exista mecanismul try-except, asemanator celui try-catch din Java.

Lucrul cu fisiere este, de asemenea, simplu. Pentru a obtine un obiect de tip fisier, se apeleaza functia open, de obicei cu doi parametri: numele (calea) fisierului si modul de acces (r - read only; w - write only si daca exista va fi suprascris; a - append; r+ - citire si scriere; rb, wb, r+b - deschide fisierul in mod binar):

f = open('input.txt','w')

Odata obtinut obiectul fisier f, se vor putea folosi functiile pentru lucrul cu fisiere: read, readline, readlines, write, seek sau close ca metode ale clasei file (exemplu: f.read()).

Uneori, pentru a scrie obiecte Python in fisiere, acestea trebuie transformate intr-un string, proces numit pickling (iar procesul invers: unpickling). Folosind modulul pickle cu functiile pickle.dump si pickle.load, acest lucru poate fi realizat cu usurinta. Urmatorul exemplu este concludent:

# Salvam un dictionar intr-un fisier folosind pickle

import pickle

 

culoare_favorita = { "caisa": "galbena", "portocala": "orange", "cireasa": "rosie" }

print culoare_favorita

 

pickle.dump( culoare_favorita, open( "save.p", "w" ) )

 

# Incarcam dictionarul inapoi din fisier folosind pickle

culoarea_mea_fav = pickle.load( open( "save.p" ) )

print culoarea_mea_fav

# culoarea_mea_fav e acum { "caisa": "galbena", "portocala": "orange", "cireasa": "rosie" }

Pentru lucrul cu siruri de caractere exista functii ajutatoare precum rstrip, lower, etc.

 

Exemple de programe rezolvate

1)      Calculul sumelor partiale a primelor N numere naturale

Iata un exemplu simplu de script Python, in care se defineste o rutina si se apeleaza. #!/usr/bin/python

# definim o functie care afiseaza numerele de la 1 la n si calculeaza suma lor

def calc_suma( n): # n este parametru al functiei

# virgula de la print suprima aparitia lui \n dupa textul tiparit

print 1,

suma = 1

i = 2

# nu uitati de ':' de la sfarsitul liniilor care preced sub-blocuri!

# adica dupa for, while, if, def etc.

while i <= n:

print "+", i,

suma += i

i += 1

print "=", suma

# raw_input citeste un string de la tastatura afisand promptul dat

# acest string se converteste la un intreg cu int(..). Daca nu se introduce un

# numar valid, se va genera o exceptie.

n = int(raw_input("Dati n="))

# range(a, b) intoarce o lista ce contine [a, a+1, ..., b-1]

for i in range(1, n+1):

calc_suma( i)

Exemplu de executie:

$ chmod +x sume_partiale.py

$ ./sume_partiale.py

Dati n=4

1 = 1

1 + 2 = 3

1 + 2 + 3 = 6

1 + 2 + 3 + 4 = 10

 

2)      Calculul numerelor prime pana la un N dat

import math # import modulul math

from sys import argv # din modulul sys import lista argv (argumente in linia de comanda)

def isPrime(x): # definesc o functie care decide daca x e prim

for i in range(2, int(math.sqrt(x)+1)): # range(a, b) => lista [a, ..., b-1]

if x % i == 0: # nu uita de ':' !

return 0

return 1

def buildPrimes(max = 100): # se poate da o valoare implicita pentru parametru

result = [] # initializez lista

for i in range(1, max+1):

if isPrime(i):

result.append(i) # adaug la sfarsitul ei un nou element

return result

# pentru ca parametrul are o valoare implicita, vom putea apela si asa: buildPrimes()

if len(argv) == 2: # argv[0]=nume script; len(argv)==2 inseamna un argument in plus

n = int(argv[1])

print buildPrimes( n)

else: # daca nu am un parametru

try:

n=int(raw_input("Dati N= ")) # raw_input citeste un string de la tastatura

 # daca a fost "prinsa" o exceptie:

except(ValueError):

print "Asteptam un numar intreg."

else:

for k in buildPrimes( n): # tiparesc fiecare numar din lista

print k,

print # print simplu inseamna de fapt newline

Exemple de executie:

$ python prim.py 30

[1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

sau

$ python prim.py

Dati N= 50

1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

Pe Windows, pentru a da un argument din linia de comanda, sunt suficiente numele scriptului si argumentul:

c:\> prim.py 30

 

Exercitii propuse

1)      Find-a-bug: Assign Gift Givers

This function is for those situations where a set of people, such as office coworkers, exchange gifts among themselves, with each person assigned to buy gifts for one other person.

This function walks the list of people and assigns a gift target to each of them. It has to ensure that no one is assigned his or her own name. In particular, with a list of N people, it needs to avoid the situation where the first N-1 people are chosen to give gifts among themselves and, when it is time to process the last person on the list, no one else is left.

The program is passed as a parameter a list of names, and returns a dictionary. In the dictionary, the keys are the same list of names, and the values are the name that each person should give a gift to.

For a Python list, the function mylist.count(x) returns the number of times that x appears in mylist.

The function mylist.pop(i)returns the element at index i of mylist, and also removes it from the list.

The function mylist.index(x)returns the index of the first occurrence of x in mylist. It's an error if x does not occur in mylist.

Source Code

 

 1.      import random

 2.

 3.      def secretSanta( inputList ):

 4.      """

 5.          inputList: A list of names

 6.

 7.          Returns a dictionary, the keys are givers' names,

 8.               the values are receivers' names.

 9.        """

10.

11.        if len(inputList) < 2:

12.          return {}

13.

14.        returnDict = {}

15.

16.        """ Make a copy of the input list; we remove people

17.           from this list as they are assigned givers.

18.        """

19.

20.        receiversList = inputList[:]

21.

22.        for person in inputList:

23.

24.          """ If there are only two receivers left, and one

25.              of them is the last person in inputList, then

26.              assign the last person to the second-to-last

27.              person.

28.          """

29.

30.          if len(receiversList) == 2:

31.            if receiversList.count(inputList[-1]) == 1:

32.              returnDict[person] = inputList[-1]

33.              returnDict[inputList[-1]] = person

34.              break;

35.

36.          """ The typical situation, just randomly pick

37.              someone out of receiversList and give them to

38.              person. We don't want to assign someone to

39.              themselves. If that happens, we assign them the

40.              next person in receiversList.

41.          """

42.

43.          if receiversList.count(person) == 1:

44.            receiverIndex = \

45.                int ((len(receiversList)-1) * random.random())

46.            if receiversList.index(person) <= receiverIndex:

47.              receiverIndex += 1

48.          else:

49.            receiverIndex = \

50.                int (len(receiversList) * random.random())

51.

52.          returnDict[person] = \

53.              receiversList.pop(receiverIndex);

54.

55.       return returnDict

Suggestions

  1. Two lists (inputList and receiversList) and one dictionary (returnDict) are used. State the goal of each one, and note which ones are modified and where.
  2. On line 46, the index() function is used to look up person in receiverList. This implies that person must be in receiverList. Is this guaranteed to be true?
  3. An invariant condition exists between returnDict and receiversList, which is that an element in one is not in the other. Check the sections of code that relate to this to ensure that the condition is always true.
  4. What is the goal of the code on lines 43–50? How many different paths to walk through exist in this code?

Hints

  1. Walk through one iteration of the code when the function was passed an inputList equal to [ "Tom", "Joe", "Donna", "Susan", "Paul" ].
  2. Imagine the same input list, but the next iteration of the main for loop on line 22, where person is "Joe", and assume the remaining receiversList is [ "Tom", "Donna", "Susan", "Paul" ].
  3. Consider the fourth iteration, where person is "Susan", and assume receiversList is now [ "Donna", "Paul" ].

 

2)      Se da o lista de numere intregi. Se cere sa se ordoneze si afiseze elementele din lista, in ordine descrescatoare.

 

3)      Scrieti o functie : fibonacci(int a) care sa calculeze elementul de pe pozitia a din sirul lui Fibonacci (1,1,2,3,5…), definit ca : Fn = Fn−1 + Fn−2.

        

Resurse

Introducerea in Python poate fi usurata prin parcurgerea unui tutorial in limba romana sau a celui de pe site-ul oficial.

Alte carti interesante sunt "Thinking in Python" si "Dive into Python". Un forum de discutii util poate fi gasit la adresa: http://www.thescripts.com/forum/forum152.html . Documentatia oficiala va sta la dispozitie aici.

In sectiunea "Resurse" a laboratorului puteti gasi mai multe exemple introductive (lab1.py).

Despre metode de stringuri puteti gasi informatii suplimentare aici.