User Tools

Site Tools


notiuni-python

Noțiuni specifice Python

Prezentare aici!

Capitolele anterioare Introducere și Sintaxă , Operații de bază și Programare Orientată Obiect prezintă noțiunile de concept general specifice unui limbaj modern. Însă Python are câteva particularități care îl transformă într-un limbaj special. Vom aborda o parte din ele în cele ce urmează.

List comprehensions

List comprehensions este un mecanism simplu, intuitiv și concis de a crea liste. Pentru acesta, se folosesc o pereche de paranteze pătrate care conțin o expresie și o buclă for, urmată sau nu de zero sau mai multe condiționale. O listă nouă va fi mereu rezultatul evaluării expresiei în contextul buclei și a conditionalelor.

>>> [x*2 for x in range(3)]
[0, 2, 4]

Sintaxa de bază este:

[ expresie for element in lista if conditionala ]

Construcția de mai sus este echivalentă cu:

for element in lista:
    if conditionala:
        expresie

Exemplu - construcția unei liste, cu și fără list comprehensions:

# folosind bucla for:
>>> patrate_perfecte = []
    for x in range(10):
        patrate_perfecte.append(x**2)
>>> print patrate_perfecte
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
 
#  alternativ, folosind list comprehensions pentru obținerea aceluiași rezultat:
>>> patrate_perfecte = [x**2 for x in range(10)]
>>> print patrate_perfecte
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Exemplu - multiplicarea fiecărui element dintr-o listă cu 3:

>>> lista = [3,4,5]
>>> lista_multiplu = [element*3 for element in lista]
>>> print lista_multiplu
[9,12,15]

Exemplu - afișarea mutiplilor lui 3 mai mici sau egali cu 50:

>>> lista = [i for i in range(50) if (i%3) == 0]
>>> lista
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48]

Un aspect important de luat în seamă este faptul că expresia inițială, lista în care se iterează sau condiționala pot lua forme mai avansate. Astfel, mecanismul de list comprehensions poate conține expresii mai complexe și funcții îmbricate.

Exemplu - afișarea numarului π (pi) cu una sau mai multe zecimale:

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

Exemplu - afișarea numerelor care se divid și cu 3 și cu 5 dar care sunt mai mici decat 50:

>>> lista = [i for i in [j for j in range(50) if (j%3)==0] if (i%5)==0]
>>> print lista
[0, 15, 30, 45]

Materiale online suplimentare:

Nested list comprehensions

Spuneam mai sus, la sfârșitul subcapitolului de list comprehensions ca elementele care compun acest mecanism pot lua forme avansate și complexe. Astfel, expresia inițială poate fi o expresie oarecare, inclusiv o altă formă de list comprehension.

Din raționament teoretic, să luam ca exemplu următoarea problemă: dându-se o matrice, să se obțină transpusa ei. Așadar, presupunem că am avea o matrice 5×4 implementată ca o listă de 5 liste cu dimensiunea 4:

>>> matrice = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... [13, 14, 15, 16],
... [17, 18, 19, 20],
... ]
>>> matrice
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]

Soluția 1 (fără ''list comprehension'')

>>> transpusa = []
>>> for i in range(4):
...     linie_transpusa = []
...     for linie in matrice:
...             linie_transpusa.append(linie[i])
...     transpusa.append(linie_transpusa)
... 
>>> transpusa
[[1, 5, 9, 13, 17], [2, 6, 10, 14, 18], [3, 7, 11, 15, 19], [4, 8, 12, 16, 20]]

Soluția 2 (cu ''list comprehension'')

>>> transpusa = []
>>> for i in range(4):
...     transpusa.append([linie[i] for linie in matrice])
... 
>>> transpusa
[[1, 5, 9, 13, 17], [2, 6, 10, 14, 18], [3, 7, 11, 15, 19], [4, 8, 12, 16, 20]]

Soluția 3 (cu ''nested list comprehension'')

>>> transpusa = [[linie[i] for linie in matrice] for i in range(4)]
>>> transpusa
[[1, 5, 9, 13, 17], [2, 6, 10, 14, 18], [3, 7, 11, 15, 19], [4, 8, 12, 16, 20]]

Prin urmare, avantajele folosirii mecanismului de nested list comprehension sunt evidente. Cu toate acestea, în practică, nu întotdeauna folosirea acestui mecanism este cea mai lizibilă soluție. Pentru a rezolva aceasta problema, limbajul Python pune la dispoziție și alte metode pe care le vom aborda însă în capitolul următor.

Dictionary comprehensions

Începând cu versiunea 2.7+ a limbajului Python, un mecanism similar celui de list comprehension a fost adăugat și pentru dicționare (e.g.dictionary comprehension). Similar celui de liste, acest mecanism creează un nou dicționar; prin urmare, acest mecanism nu poate fi folosit pentru a adăuga chei într-un dicționar deja existent. Așadar, contextul de perechi cheie-valoare trebuie precizat la construcție.

Exemplu - afișarea primelor 10 pătrate perfecte:

>>> d = {n: n**2 for n in range(10)}
>>> d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

Exemplu - setarea tuturor cheilor la valoarea booleana True pentru primele 10 numerele naturale:

>>> d = {n: True for n in range(10)}
>>> d
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True, 6: True, 7: True, 8: True, 9: True}

Materiale online suplimentare:

Map/Lambda/Filter

map(), lambda și filter(), alături de mecanismul de list comprehensions furnizează un mod compact, elegant, și eficient de a programa.

Map

Este o construcție builtin în Python care aplică o funcție fiecărui membru dintr-o colecție iterabilă, oricare ar fi ea (listă, tuplu, etc) și întoarce rezultatul.

Exemplu - afișarea primelor zece pătrate perfecte (rescrierea exemplului de la list comprehensions):

>>> def patrat(x):
        return x**2 
>>> patrate_perfecte = map(patrat, range(10))
>>> print patrate_perfecte
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Exemplu - putem folosi și o funcție builtin (e.g. len) în construcția map():

>>> nume = ['Gigel', 'Costel', 'Dorel', 'Fanel', 'Ana', 'Viorica']
>>> lungimi = map(len, nume)
>>> print lungimi
[5, 6, 5, 5, 3, 7]

Lambda

În primul exemplu de mai sus din cadrul construcției map am creat o funcție numita patrat pentru a putea fi aplicată în context peste secvența dată. Aceasta este o situație des întâlnită în Python. Ca urmare, limbajul pune la dispoziția programatorului o metodă mai flexibilă și mai robustă de a crea funcții simple anonime (fară declarații suplimentare în blocul de execuție) cu ajutorul așa numitei funcții lambda. Așadar, o funcție simplă, anonimă care returnează rădăcina pătrată a argumentului transmis poate fi rescrisă astfel: lambda x: x ** 2. În traducere liberă expresia înseamnă: O funcție anonimă (fără nume) care primește un argument x și returnează rădăcina pătrată a acestuia.

Alte exemple de utilizare a funcției lambda:

>>> print (lambda x: x**2)(5) # primul set de paranteze definesc funcția lambda, al doilea set de paranteze apelează funcția
25
>>> # creează o funcție cu două argumente (x și y) care returnează produsul lor, apoi apelează funcția cu argumentele 3 și 4
>>> print (lambda x, y: x*y)(3, 4)
12
>>> print (lambda x: x.startswith('G'))('Gigel')
True
>>> print (lambda x: x.startswith('B'))('Costel')
False
>>> incrementer = lambda input: input+1
>>> print incrementer(3)
4

Filter

Este de asemenea o construcție builtin în Python care primește ca argument o funcție care întoarce True sau False și o aplică pe o secvență, întorcând ca rezultat o listă care conține doar acele elemente din secvență pentru care funcția aplicată întoarce True.

Exemplu - putem rescrie o parte din exemplele de mai sus, mai succint, astfel încât sa obținem pătratele perfecte între mai mari decat 10 dar mai mici decat 50:

>>> patrate = map(lambda x: x**2, range(10))
>>> lista = filter(lambda x: x > 10 and x < 50, patrate)
>>> print lista
[16, 25, 36, 49]

Exemplu - afișarea numelor care conțin sufixul “el” dintr-o listă:

>>> nume = ['Gigel', 'Costel', 'Dorel', 'Fanel', 'Ana', 'Viorica']
>>> lista = filter(lambda s: s.endswith('el'), nume)
>>> print lista
['Gigel', 'Costel', 'Dorel', 'Fanel']

Materiale online suplimentare:

dir()

În capitolul de Operații de bază, spuneam că limbajul Python are un set de funcții foarte folositoare pe care le pune la dispoziție în mod direct (e.g. string(), type(), funcții de conversie, funcții matematice, etc). Din aceeași categorie, o altă funcție importantă este funcția dir().

Extrem de utilă în cazuri simple dar mai ales în contextul programării orientate-obiect, funcția dir() întoarce o listă de atribute și metode ale unui obiect, oricare ar fi acesta: modul, funcție, string, listă, dicțtionar, etc.

Exemplu - utilizarea funcției dir() pe o listă:

>>> dir(li)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Exemplu - utilizarea funcției dir() pe un dicționar:

>>> d = {}
>>> dir(d)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']

Exemplu - utilizarea funcției dir() pe modulul string:

>>> import string
>>> dir(string)
['Formatter', 'Template', '_TemplateMetaclass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_float', '_idmap', '_idmapL', '_int', '_long', '_multimap', '_re', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'atof', 'atof_error', 'atoi', 'atoi_error', 'atol', 'atol_error', 'capitalize', 'capwords', 'center', 'count', 'digits', 'expandtabs', 'find', 'hexdigits', 'index', 'index_error', 'join', 'joinfields', 'letters', 'ljust', 'lower', 'lowercase', 'lstrip', 'maketrans', 'octdigits', 'printable', 'punctuation', 'replace', 'rfind', 'rindex', 'rjust', 'rsplit', 'rstrip', 'split', 'splitfields', 'strip', 'swapcase', 'translate', 'upper', 'uppercase', 'whitespace', 'zfill']

Observații:

  • li este o listă, așadar dir(li) returnează o listă cu toate metodele unei liste. Lista întoarsă conține numele metodelor ca stringuri
  • string în ultimul exemplu este un modul, așa încât dir(string) întoarce o listă cu mai multe tipuri de rezultate (e.g. atribute built-in ca __name__, __doc__, și/sau alte atribute definite de programator)

[Bonus] Metode "magice"

Ce sunt așa numitele metode “magice”? Ele sunt nucleul programării orientate pe obiecte în Python. Sunt metode speciale care pot fi definite pentru a adăuga puțină “magie” in clasele definite de programator. Ușor de recunoscut, se definesc intotdeauna prefixate și sufixate de o pereche de _.(e.g. __init__ sau __lt__).

În capitolul de Programare Orientată Obiect am făcut cunoștiință cu cea mai cunoscută metodă “magică” și-anume init. Spuneam atunci ca ea este rulată imediat ce o clasă este instanțiată (constructor) și că este utilă în special pentru a adăuga diferite inițializări. Cu toate acestea însă, în momentul în care apelăm x = ClasaOarecare(), metoda __init__ nu este prima metodă apelată. Ea este precedată de o altă metodă numita __new__ care defapt creează instanța și o trimite mai departe metodei de inițializare împreuna cu contextul de argumente. La sfârșitul ciclului de viață pentru obiectul respectiv se apelează __del__. Detaliat, cele trei metode amintite mai sus sunt:

  • __new__(cls, […)
    • __new__ este prima metoda apelată în momentul instanțierii unui obiect. Ea primește ca parametrii tipul clasei urmată de orice alt argument pe care le va transmite mai departe metodei __init__. __new__ este folosită destul de rar, însă are particularitățile ei specifice.
  • __init__(self, […)
    • Metoda de inițializare a clasei. Primește ca argument orice parametru a fost transmis în momentul apelării constructorului (de exemplu, daca am fi apelat x = SomeClass(10, 'foo'), __init__ ar fi primit ca argumente 10 și foo. __init__ este folosită universal in definirea claselor în Python.
  • __del__(self)
    • Dacă __new__ și __init__ formează împreună constructorul clasei, __del__ este destructorul. Atentie! El nu implementează comportamentul instructiunii del x (deci codul nu se traduce prin x.del()!!). Mai degrabă acesta completează comportamentul obiectului în momentul în care este eliberata memoria (util de exemplu în situația sockets-ilor sau a fișierelor obiect)

Exemplu de clasa care face uz de cele menționate mai sus:

from os.path import join
 
class FisierObiect:
    '''Clasa wrapper la fisierele obiect pentru a asigura inchiderea handler-ului de citire inainte ca fisierul sa fie sters.'''
 
    def __init__(self, cale_fisier='~', nume_fisier='exemplu.txt'):
        # deschide fisierul nume_fisier din cale_fisier in modul de citire/scriere
        self.file = open(join(cale_fisier, nume_fisier), 'r+')
 
    def __del__(self):
        self.file.close()
        del self.file

Python pune la dispoziția programatorilor o întreagă gamă de metode “magice”:

  • metode magice de comparatie: __cmp__, __eq__, __ne__, __lt__, __gt__, etc
  • metode magice numerice: __pos__, __neg__, __abs__, __invert__, __round__, etc
  • metode magice pentru operatii aritmetice: __add__, __sub__, __mul__, __div__, __mod__, etc
  • metode magice pentru atribuire augmentata: __iadd__, __isub__, __imul__, __idiv__, __imod__, etc
  • metode magice pentru conversii de tip: __int__, __long__, __float__, __complex__, __hex__, etc
  • metode magice pentru reprezentivitatea clasei:
    • __str__ definește comportamentul funcției str() atunci cand aceasta este apelată cu instanța acestei clase
    • * __repr__ definește comportamentul funcției repr() atunci cand aceasta este apelată cu instanța acestei clase. Diferența majoră între str() și repr() o reprezintă instanța care le apelează. repr() este folosită de principiu pentru a produce output machine-readable, în timp ce str() produce output human-readable.
    • __unicode__ definește comportamentul funcției unicode() atunci cand aceasta este apelată cu instanța acestei clase. unicode() se comportă precum str() însă întoarce un string unicode.
    • s.a.m.d

Dintre aceste metode “magice”, vom exemplifica patru dintre ele, care au o importanță majoră: __getitem__, __call__, __getattr__, __setattr__.

__getitem__

Implementarea metodei __getitem__ într-o clasă permite instanțelor sale să folosească operatorul de indexare [].

class Test(object):
    def __getitem__(self, items):
        print '%s %s' % (type(items), items)
 
t = Test()
t[1]
t['salut studenti!']
t[1, 'b', 3.0]
t[5:200:10]
t['a':'z': 3]
t[object()]

Va produce urmatorul output la consola de rulare a codului Python:

<type 'int'> 1
<type 'str'> salut studenti!
<type 'tuple'> (1, 'b', 3.0)
<type 'slice'> slice(5, 200, 10)
<type 'slice'> slice('a', 'z', 3)
<type 'object'> <object object at 0x10a1580a0>

Observații:

  • Spre deosebire de alte limbaje, Python permite transmiterea oricarui tip de obiect prin operatorul de indexare []. Astfel, expresia t[1, 'b', 3.0] este parsată fără probleme de interpretor. În mecanismul intern, aceasta instrucțiune se traduce prin t.__getitem__((1, 'b', 3.0)) (tratată ca un tuplu)
  • __getitem__ este de cele mai multe ori folosită pentru indexarea listelor, căutare in dicționare sau accesarea unor intervale de valori

__call__

Implementarea metodei __call__ într-o clasă permite instanțelor sale să devină apelabile – cu alte cuvinte, acele instanțe se comportă ca niște funcții. Pentru a testa dacă un anumit obiect este sau nu apelabil se poate folosi metoda built-in callable (returnează True pentru funcții, metode și obiecte care au __call__

class Test(object):
    def __call__(self, *args, **kwargs):
        print args
        print kwargs
        print '-'*30
 
t = Test()
t(1, 2, 3)
t(a=1, b=2, c=3)
t(4, 5, 6, d=4, e=5, f=6)

Va produce urmatorul output la consola de rulare a codului Python:

(1, 2, 3)
{}
------------------------------
()
{'a': 1, 'c': 3, 'b': 2}
------------------------------
(4, 5, 6)
{'e': 5, 'd': 4, 'f': 6}
------------------------------

Observații:

  • Metoda “magică” __call__ se implementează ca orice altă metodă sau funcție. Singura diferență este ca pentru a o apela, nu e nevoie de un nume ci doar de paranteze rotunde ().

__getattr__

Implementarea metodei __getattr__ într-o clasă permite instanțelor sale să suprascrie mecanismul de acces la membri.

class Test(object):
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
 
    def __getattr__(self, name):
        return 123456
 
t = Test()
print 'variabilele obiectuluiȘ %r' % t.__dict__.keys()
print t.a
print t.b
print t.c
print getattr(t, 'd')
print hasattr(t, 'x')

Va produce următorul output la consola de rulare a codului Python:

variabilele obiectului ['a', 'b']
a
b
123456
123456
True

Observații:

  • După cum se poate observa din exemplul de mai sus, metoda __getattr__ este invocată doar pentru atribute care nu se regăsesc în atributul “magic” __dict__. Implementarea __getattr__ face ca metoda built-in hasattr() sa întoarcă mereu True, cu excepția cazului în care o excepție este aruncată în mod expres în blocul de instrucțiuni al metodei __getattr__.

__setattr__

Deși implementarea metodei __setattr__ nu este foarte întâlnită, am considerat că este bine să fie amintită pentru o privire de ansamblu. Implementarea ei într-o clasă permite instanțelor sale să suprascrie mecanismul de atribuire al membrilor.

class Test(object):
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
 
    def __setattr__(self, name, value):
        print 'setat %s la %s' % (name, repr(value))
 
        if name in ('a', 'b'):
            object.__setattr__(self, name, value)
 
t = Test()
t.c = 'z'
setattr(t, 'd', '888')

Va produce următorul output la consola de rulare a codului Python:

setat a la 'a'
setat b la 'b'
setat c la 'z'
setat d la '888'

Observații:

  • Surprinzător sau nu, metoda __setattr__ nu este simetrică cu __getattr__!! În particular, toate atribuirile trec prin __setattr__, chiar și pentru variabilele prezente in atributul “magic” __dict__ . Din acest motiv, implementarea lui __setattr__ nu este recomandată.

Materiale online suplimentare:

Exercitii

Observație: Folosiți cât mai mult mecanismele de list comprehension și/sau map/filter/lambda.

1. Scrieți o funcție care primește ca argument o listă L de cuvinte și întoarce ca rezultat o altă listă care conține prima litera din fiecare cuvânt al listei inițiale.

  • Soluție
    >>> l = ['Ana', 'are', 'mere', 'iar', 'Costel', 'are', 'pere']
    >>> l2 = [word[0] for word in l]
    >>> print l2
    ['A', 'a', 'm', 'i', 'C', 'a', 'p']

2. Scrieți o funcție care primește ca argument o listă L de cuvinte și întoarce ca rezultat o altă listă care conține aceleași cuvinte din lista inițială dar scrise cu majuscule.

  • Soluție
    >>> l = ['ana', 'are', 'mere', 'iar', 'costel', 'are', 'pere']
    >>> l2 = [word.upper() for word in l]
    >>> print l2
    ['ANA', 'ARE', 'MERE', 'IAR', 'COSTEL', 'ARE', 'PERE']

3. Scrieți o funcție care primește ca argument o listă L și întoarce ca rezultat o altă listă care conține toate elementele din L duplicate.

  • Soluție
    >>> def dupli(L):
    ...     return [x for x in L for i in (1,2)]
    ... 
    >>> dupli([1, 2, 3, 4, 5])
    [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]

4. Scrieți o funcție care primește ca argument o listă L și un număr întreg N, și întoarce ca rezultat o altă listă care conține toate elementele din L duplicate de N ori.

  • Soluție
    >>> def dupli(L, N):
    ...     return [x for x in L for i in range(N)]
    ... 
    >>> dupli([1, 2, 3], 5)
    [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]

5. Scrieți o funcție, care primește ca argument o listă L și un număr întreg N, care șterge fiecare al N-lea element din listă.

  • Soluție
    >>> def drop(L, N):
    ...     return [x for i,x in enumerate(L) if (i+1) % N]
    ... 
    >>> drop([1, 2, 3, 1, 2, 24, 3, 3, 2, 234, 1234], 3)
    [1, 2, 1, 2, 3, 3, 234, 1234]

6. Scrieți o funcție care primește ca argument două liste L1 și L2 și întoarce ca rezultat o listă conținând toate elementele care se află în L1 dar nu în L2.

  • Soluție
    >>> def separate(L1, L2):
    ...   return [x for x in L1 if x not in L2]
    ... 
    >>> separate([1, 2, 3], [4, 5, 6])
    [1, 2, 3]
    >>> separate([1, 2, 3, 4, 5, 6], [4, 5, 6])
    [1, 2, 3]
    >>> separate([1, 2, 3, 4, 5, 6], [1, 2, 4, 5, 6])
    [3]

7. Dându-se o listă L de cuvinte și o altă listă suf de sufixe, scrieți o funcție care întoarce cuvintele din L cu sufixul eliminat dacă acesta se regăsește în suf. Observație: dacă un cuvânt conține mai mult de un sufix din suf, se elimină cel mai lung dintre ele.

  • Soluție
    >>> def token_stemming(L1, suf):
        result = []
        suf.sort(key=lambda item: (-len(item), item))
        for word in L1:
            found_suffix = False
            for suffix in suf:
                if word.endswith(suffix):
                    result.append(word[:-len(suffix)])
                    found_suffix = True
                    break
            if not found_suffix:
                result.append(word)
        return result
    >>> token_stemming(["friendly", "outgoing", "powerful", "in"], ["ing", "ly", "ul", "ful"])
    ['friend', 'outgo', 'power', 'in']

8. Scrieți o funcție care primește oricâte numere și întoarce suma celor impare.

  • Soluție
    >>> def odd(*args):
            for arg in args:
                if (arg%2 == 1):
                    yield arg
     
    >>> sum_of_odds = sum(odd(1, 2, 3, 4, 5))
    >>> print sum_of_odds
    9

9. Dându-se o listă L de cuvinte și un număr întreg N, scrieți o funcție care întoarce cele mai frecvente N cuvinte din listă.

  • Soluție
    >>> def count_words(L, N):
        freq = {}
        for word in L:
            if word in freq:
                freq[word] += 1
            else:
                freq[word] = 1
     
        sorted_frequencies = sorted(freq.iteritems(), key=operator.itemgetter(1))
        sorted_frequencies.reverse()
     
        return [t[0] for t in sorted_frequencies[:N]]
     
    >>> count_words(['Gigel', 'si', 'Costel', 'si', 'iar', 'Costel', 'fug', 'de', 'celalalt', 'Gigel'], 3)
    ['Gigel', 'si', 'Costel']

10. Scrieți o funcție care afișează suma primelor 1000000 de numere naturale folosind generatori.

  • Soluție
    >>> def firstn(n):
        num = 0
        while num < n:
            yield num
            num += 1
     
    >>> sum_of_first_n = sum(firstn(1000000))
    499999500000
notiuni-python.txt · Last modified: 2014/01/08 06:03 by mihait