Python 3_V1.2.pdf

May 5, 2017 | Author: mihaineag91 | Category: N/A
Share Embed Donate


Short Description

Download Python 3_V1.2.pdf...

Description

Python 3

2012 memIQ

Python 3

DV1.2 - 16042012

1

Python 3

2012 memIQ

Cuprins 1

2

3

4

5

6

7

Introducere

4

1.1

Crearea și executarea programelor Python

4

1.2

Start...

5

Tipuri de date

12

2.1

Identificatori și cuvinte cheie

12

2.2

Tipuri întregi

12

2.3

Tipuri în virgulă mobilă

13

2.4

Șiruri de caractere

14

2.5

Exemple

22

Colecții

24

3.1

Tipuri secvență

24

3.2

Mulțimi

28

3.3

Map-uri

29

3.4

Iterarea și copierea colecțiilor

32

3.5

Exemple

35

Structuri de control și funcții

36

4.1

Structuri de control

36

4.2

Tratarea excepțiilor

37

4.3

Funcții

40

4.4

Exemplu

46

Module

47

5.1

Module

47

5.2

Pachete

48

5.3

Exemplu

49

5.4

Biblioteca standard Python

50

Programare orientată pe obiecte

58

6.1

Concepte OO

58

6.2

Clase definite de utilizator

58

6.3

Clase colecție personalizate

64

Lucrul cu fișierele 7.1

71

Fișiere binare

DV1.2 - 16042012

72 2

Python 3

8

9

10

7.2

Fișiere text

74

7.3

Fișiere XML

77

7.4

Exerciții

84

Tehnici avansate

85

8.1

Programare procedurală

85

8.2

OOP

93

8.3

Programare functionala

106

8.4

Exemplu

108

Procese și fire de execuție

12

110

9.1

Modulul subprocess

110

9.2

Modulul threading

110

9.3

Modulul multiprocessing

110

9.4

Exemplu

110

Lucrul în rețea – networking 10.1

11

2012 memIQ

111

Exemplu

111

Baze de date

112

11.1

Baze de date DBM

112

11.2

Baze de date SQL

112

Referințe

DV1.2 - 16042012

114

3

Python 3

2012 memIQ

1 Introducere Caracterizare: http://python.org/doc/essays/blurb.html Python: • Limbaj foarte expresiv • Interpretat – portabilitate peste platformele cele mai diverse • Biblioteca standard completă; biblioteci pentru cele mai diverse probleme http://pypi.python.org/pypi • Limbaj cu caracteristici procedurale, orientat pe obiecte, calități de programare funcțională Obiectivul – limbajul Python. Instalare – test în consolă: python –V (python3, python3.1, etc.). Kit instalare - www.python.org/download IDE (Integrated Development Environment): • Orice editor text • PSPad • IDLE (Python Shell) • Eclipse + Pydev - http://pydev.org

1.1 Crearea și executarea programelor Python -

ASCII sau UTF-8 (implicit) Fișiere cu extensia py, pyw (GUI) sau fără extensie

Exemplu: hello.py #!/usr/bin/env python print("Hello", "World!") -

# - comentariu

-

Execuția se face linie cu linie începând de sus

-

path – drumul la python.exe (sau legături simbolice)

-

asociere în Windows a extensiei py cu python.exe

-

prima linie: #!/usr/bin/python3

DV1.2 - 16042012

- interpreter 4

Python 3

2012 memIQ

sau: #!/usr/bin/env python3 - variabila de mediu conține interpreterul

1.2 Start... a) Tipuri de date -

Tipuri de date incluse în limbaj, predefinite int – limitat de memoria mașinii str – se folosesc “” sau ‘’ [] – acces la o secvență (primul are index 0), inclusiv str – “casa”[2] int si str sunt imutabile conversie – cast: datatype(element) – int(“100”) --> 100 int() – este tolerant la spații (trim) se generează o excepție dacă conversia nu reușește

b) Referințe la obiecte -

Variabilele țin referințe la obiecte: x = “casa” Operatorul = leagă un obiect de o referință Nu trebuie predeclarate, nu trebuie specificat tipul Dacă un obiect nu mai este referit - va fi distrus de garbage collector Identificatorii trebuie să înceapă cu literă sau _; case sensitive, orice lungime Dynamic typing – o referință se poate lega dinamic de un alt tip, va permite operații valabile doar pentru acel tip Exemplu: X = 100 print(X, type(X))

# 100

c) Colecții de date -

Tuple, liste – pot ține orice număr de elemente de orice tip; Tuple – imutabile – (, ex: (1,) Liste – mutabile – [, În colecție se țin referințe Elemente în colecții pot fi alte colecții Tipuri cu mărime (sized) – len() len((1,5)) len(“casa”)

-

Obiectele sunt instanțe de clase Obiectele au metode; apel prin calificare x = [“a”, “fost”] x.append(“casa”) list.append(x, “casa”)

DV1.2 - 16042012

5

Python 3 -

2012 memIQ

list: insert(), remove() Acces la elemente prin []; x[0] = “masa” – doar pentru liste, nu tuple!

d) Operații Operatorul de identitate - is -

Test dacă referințele indică spre același obiect (identitate):

Exemplu: a = [“casa”, 1, None] b = [“casa”, 1, None] a is b False a=b a is b True Testați:

Nu se testează egalitatea valorilor int sau str, se testează identitatea obiectelor spre care indică referințele Rapid – se testează adresele obiectelor în memorie a=1 b=1 a is b

Exemplu: a = None b=1 b is not a True

Operatori de comparare -

< >= == != Se compară valorile obiectelor, nu identitatea lor Pentru compararea str se folosesc codurile UNICODE Se pot inlănțui operatorii: a=3 0 out.txt

-

Exemplul sum2.py < sum2.dat

h) Funcții def numeFunctie(argumente): suite -

Argumentele sunt opționale și sunt despărțite prin virgule Orice funcție întoarce o valoare, implicit None Return – valoare sau un tuplu def – obiect funcție, referința este numele funcției; se pot pune în colecții și pasate ca parametrii

Exemplu: def get_int(msg): while True: try: i = int(input(msg)) return i except ValueError as err: print(err) Folosire: x = get_int(“Introduceti un intreg: ”) -

module – conțin funcții, clase, variabile; vezi echoargs.py Folosire: import sys print(sys.argv)

-

module standard – litere mici modulele se importă la începutul fișierului sursă

Exemplu: import random x = random.randint(1,4) y = random.choice([“casa”, “masa”, “om”]) Exemple: bigdigits.py, generate_grid.py DV1.2 - 16042012

10

Python 3

2012 memIQ

Temă: construiți un program care acceptă de la consolă un șir de numere pe care le afișează apoi sortat (fără a folosi o funcție bibliotecă), împreună cu suma și media lor aritmetică.

DV1.2 - 16042012

11

Python 3

2012 memIQ

2 Tipuri de date Tipuri incluse în limbaj sau din modulele standard (caz în care se referă pe baza numelui modulului, în plus modulul trebuie importat).

2.1 Identificatori și cuvinte cheie -

Reguli pentru nume Case sensitive, se folosesc caractere Unicode Cuvintele cheie sunt rezervate, nu se pot folosi ca și nume Cuvinte cheie: and as assert break class

-

-

continue def del elif else

except global False if finally import for in from is

lambda None nonlocal not or

pass while raise with return yield True try

Nu se folosesc: o identificatori folosiți de Python (ex. NotImplemented) o nume de tipuri incluse în limbaj – int, float, list, str, tuple o nume de funcții Python o nume de excepții Python dir() – listează atributele unui obiect dir() – fără atribute listează atributele Python: ['__builtins__', '__doc__', '__name__', '__package__'] – listează excepții (încep cu literă mare), funcții și tipuri de date

-

dir(__builtins__) nu se folosesc nume care încep și se termină cu __ (doi underscore) – se folosesc pentru metode și variabile speciale (ex. __lt__) numele care încep cu unul sau două caractere underscore au semnificație specială identificatorul _ ține valoarea ultimei expresii evaluate doar în interpretorul interactiv sau Python Shell: for _ in (0,1,2): print(_)

-

dacă se folosesc identificatori invalizi se generează excepția SyntaxError

2.2 Tipuri întregi -

int și bool – imutabile întregii pot fi oricât de mari, limitați doar de memorie

DV1.2 - 16042012

12

Python 3

2012 memIQ

-

True (1), False (0) – valori numerice

-

Operații: o x // y – împărțire întreagă o x % y – modulo o x ** y – ridicare la putere Funcții: o abs(x) – valoarea absolută o divmod(x,y) – cât și rest ca și tuplu o pow(x,y) – ridicare la putere o pow(x,y,z) – (x**y) % z o round(x,n) – n pozitiv sau negativ; ex: round(1234, -2) o bin(i) – reprezentarea binară a lui i o hex(i) o oct(i) o int(x) o int(s, base) constante în baza 2 (0b), 8 (0o), 16 (0x) x = 1 – se creează un obiect crearea unui obiect pe baza tipului: o tip fără argument – x = int() – se folosește valoarea implicită o un argument: de același tip – se creează un obiect prin shallow copy alt tip – se incearcă conversie; se poate genera ValueError sau TypeError o mai multe argumente – daca există mod de a crea obiectul! Operatii pe biti - | ^ & ~ > ( |= ^= …) int.bit_lenght() – returnează numătul de biți necesari pentru a reprezenta acel întreg; exemlu: (2231).bit_length()

-

-

-

Tipul Boolean – bool - True, False - obiecte

2.3 Tipuri în virgulă mobilă float -

Built in: float și complex Biblioteca standard: decimal.Decimal – pentru precizie (implicit precizie de 28 cifre) toate sunt imutabile aritmetica cu valori de tipuri diferite; float + complex = complex, …

x = float() x = float(2) test de egalitate între două numere float

def equal_float(a,b): return abs(a-b) >> circle = Circle(-2) Traceback (most recent call last): ... AssertionError: radius must be nonzero and non-negative >>> circle = Circle(4) >>> circle.radius = -1 Traceback (most recent call last): ... AssertionError: radius must be nonzero and non-negative >>> circle.radius = 6 """ return self.__radius @radius.setter def radius(self, radius): assert radius > 0, "radius must be nonzero and non-negative" self.__radius = radius __radius – este privat! Se preferă atribute în loc de metode seter & geter ca în alte limbaje fiindcă nu afectează utilizatorul clasei. În Circle init va apela atributul radius pentru inițializare! def __init__(self, radius, x=0, y=0): super().__init__(x, y) self.radius = radius

Exemplu: clasa FuzzyBool (vezi FuzzyBool.py) - False – 0.0; True – 1.00; 0.25 – 25% True - Folosire: a = FuzzyBool.FuzzyBool(.875) b = FuzzyBool.FuzzyBool(.25) a >= b # returns: True bool(a), bool(b) # returns: (True, False) ~a # returns: FuzzyBool(0.125) a&b # returns: FuzzyBool(0.25) b |= FuzzyBool.FuzzyBool(.5) # b is now: FuzzyBool(0.5) "a={0:.1%} b={1:.0%}".format(a, b) # returns: 'a=87.5% b=50%' -

Cerințe: o Suport pentru toți operatorii de comparare - < = >

DV1.2 - 16042012

61

Python 3

2012 memIQ o o o o

-

Operatori logici - ~ & | conjuction(), disjunction() conversii la bool, int, float, str să suporte specificatorul de format

Implementare 1 – from scratch (FuzzyBool.py): o __value – privat o __invert__() – ~ (not) o __and__() – & (and) o __iand__() - &= (i – in place) - return self !! o __rand__() - r – reflected – ordinea operanzilor este inversata o __repr__() – forma reprezentațională obj.__class__ - referință la obiectul clasă a obiectului, dictionar: __name_, __module__(modulul în care este definit), __bases__(clasele de baza), __doc__ (docstring), __dict__ (dicționar cu spațiul de nume al clasei) o __str__() - conversii la string o __bool__() o __int__() o __float__() o __lt__() - comparații; suficient < = width - 5 or y < 5 or y >= height - 5: image[x, y] = border_color elif midx - 20 < x < midx + 20 and midy - 20 < y < midy + 20: DV1.2 - 16042012

64

Python 3

2012 memIQ image[x, y] = square_color

image.save() image.export("square_eye.xpm") -

-

Toate atributele dată sunt private (precedate prin __), mai puțin filename Proprietăți (get): background, width, height, colors o Trebuie avut în vedere dacă atributul este imutabil sau mutabil; pentru cele mutabile se poate prefera să se furnizeze o copie pentru a nu se modifica direct proprietatea – vezi proprietatea colors Aplicarea operatorului [] la obiect: def __getitem__(self, coordinate): assert len(coordinate) == 2, "coordinate should be a 2-tuple" if (not (0 = end: raise IndexError("no record at index position {0}".format( index)) self.__fh.seek(offset) def __delitem__(self, index): self.__seek_to_index(index) state = self.__fh.read(1) if state != _OKAY: return self.__fh.seek(index * self.__record_size) self.__fh.write(_DELETED) if self.auto_flush: self.__fh.flush() def undelete(self, index): self.__seek_to_index(index) state = self.__fh.read(1) if state == _DELETED: self.__fh.seek(index * self.__record_size) self.__fh.write(_OKAY) if self.auto_flush: self.__fh.flush() return True DV1.2 - 16042012

83

Python 3

2012 memIQ return False

-

inplace_compact() compact()

modulul BikeStock: clase Bike, BikeStock – foloseste un BinaryRecordFile -

BikeStock – dictionary bike identity --> index

7.4 Exerciții 1. Modificați clasa BinaryRecordFile să nu mai folosească byte-ul de stare; ștergerea să se facă doar fizic! 2. xdump: Usage: xdump.py [options] file1 Options: -h, --help show this help message and exit -b BLOCKSIZE, --blocksize=BLOCKSIZE block size (8..80) [default: 16] -d, --decimal decimal block numbers [default: hexadecimal] -e ENCODING, --encoding=ENCODING encoding (ASCII..UTF-32) [default: UTF-8] -

3 coloane: o numărul blocului o blocul în cifre hexa o caractere

DV1.2 - 16042012

84

Python 3

2012 memIQ

8 Tehnici avansate 8.1 Programare procedurală

8.1.1Execuție pe baza unui dicționar -

Functiile sunt obiecte; numele functiilor sunt referinte la acele obiecte In loc de test si apel de functie: functions = dict(a=add_dvd, e=edit_dvd, l=list_dvds, r=remove_dvd, i=import_, x=export, q=quit) functions[action](db)

-

Exemplu din convert-incidents.py: def import_(self, filename, reader=None): extension = os.path.splitext(filename)[1].lower() call = {(".aix", "dom"): self.import_xml_dom, (".aix", "etree"): self.import_xml_etree, (".aix", "sax"): self.import_xml_sax, (".ait", "manual"): self.import_text_manual, (".ait", "regex"): self.import_text_regex, (".aib", None): self.import_binary, (".aip", None): self.import_pickle} result = call[extension, reader](filename) if result == False: self.clear() return result

8.1.2 Expresii si functii generator Am vazut functii generator (folosesc yield) Sintaxa expresie generator (sintaxa similara cu list comprehension []): (expression for item in iterable) (expression for item in iterable if condition) Echivalent - iteratori: def items_in_key_order(d): for key in sorted(d): yield key, d[key] def items_in_key_order(d): return ((key, d[key]) for key in sorted(d)) DV1.2 - 16042012

85

Python 3 -

2012 memIQ

Se pot folosi pentru a obtine valorile deodata – argumente pentru list, tuple def fu(d): for x in sorted(d): yield x lista = [4, 7, 44, 2, 55, 88, 22, 1] l1 = list(fu(lista)) l1 [1, 2, 4, 7, 22, 44, 55, 88]

-

Se pot folosi pentru iterare: for x in fu(lista): print (x)

-

Lazy evaluation (generare fara oprire!): def quarters(next_quarter=0.0): while True: yield next_quarter next_quarter += 0.25 folosire: result = [] for x in quarters(): result.append(x) if x >= 1.0: break

-

Variant care reseteaza valoare genratorului: def quarters(next_quarter=0.0): while True: received = (yield next_quarter) if received is None: next_quarter += 0.25 else: next_quarter = received folosire: result = [] generator = quarters() while len(result) < 5: x = next(generator) if abs(x - 0.5) < sys.float_info.epsilon: x = generator.send(1.0) result.append(x)

DV1.2 - 16042012

86

Python 3

2012 memIQ

Exemplul magic-numbers.py -

Pentru specificarea fisierelor de intrare (nume, masca - *.txt): if sys.platform.startswith("win"): def get_files(names): for name in names: if os.path.isfile(name): yield name else: for file in glob.iglob(name): if not os.path.isfile(file): continue yield file else: def get_files(names): return (file for file in names if os.path.isfile(file))

8.1.3 Executie dinamica de cod -

Cod introdus de utilizator, plug-ins

-

Functia built-in eval(): x = eval(“2345 – 78”)

-

Crearea si folosirea unei functii in mod dinamic: import math code = ''' def area_of_sphere(r): return 4 * math.pi * r ** 2 ''' context = {} context["math"] = math exec(code, context) o comunicarea cu functia se poate face doar printr-un dictionar context dat ca parametru la exec() o functia globals() intoarce o referinta la dictionarul global; obiectele create de exec() vor fiadaugate la acest dict; o solutie este sa dam acces la o copie a dict global: context = globals.copy() o folosire functie definite dinamic: area_of_sphere = context[“area_of_sphere”] area = area_of_sphere(10)

DV1.2 - 16042012

87

Python 3

2012 memIQ

8.1.4 Importul dinamic de module Exemplul magic-numbers.py: citeste primii 1000 bytes din fiecare fisier dat in linia de comanda, pentru fiecare va raporta tipul lui pe baza unor semnaturi continute in module aflate in acelasi director cu programul. Modulele au “magic” in nume, sunt incarcate dinamic, ofera o punctie publica get_file_type(). def main(): modules = load_modules() get_file_type_functions = [] for module in modules: get_file_type = get_function(module, "get_file_type") if get_file_type is not None: get_file_type_functions.append(get_file_type) for file in get_files(sys.argv[1:]): fh = None try: fh = open(file, "rb") magic = fh.read(1000) for get_file_type in get_file_type_functions: filetype = get_file_type(magic, os.path.splitext(file)[1]) if filetype is not None: print("{0:.= 0" return result return wrapper

Decoratori cu parametrii @bounded(0, 100) def percent(amount, total): return (amount / total) * 100 implementare: DV1.2 - 16042012

90

Python 3

2012 memIQ

def bounded(minimum, maximum): def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs): result = function(*args, **kwargs) if result < minimum: return minimum elif result > maximum: return maximum return result return wrapper return decorator

Logging function Exemplu: functie de logging pentru a inregistra pentru o functie numele, argumentele si rezultatul: @logged def discounted_price(price, percentage, make_integer=False): result = price * ((100 - percentage) / 100) if not (0 < result rexp: suite -

Optionale; se pot annota toate, unele, niciun parametru Sunt adaugate la dictionarul __annotations__ asociat obiectului functie; cheile sunt numele parametrilor, valorile sunt expresiile corespunzatoare. Nu au nici o semnificatie pentru Python, doar le pune acolo

Exemplu: vezi Util.py def is_unicode_punctuation(s : str) -> bool: for c in s: if unicodedata.category(c)[0] != "P": # punctuation return False return True Apel: Util.is_unicode_punctuation("zebr\a") Util.is_unicode_punctuation(s="!@#?") Util.is_unicode_punctuation(("!", "@"))

# returns: False # returns: True # returns: True

Putem folosi annotarea pentru verificarea de tip; decorator pentru verificarea de tip a parametrilor si a valorii returnate: def strictly_typed(function): annotations = function.__annotations__ arg_spec = inspect.getfullargspec(function) assert "return" in annotations, "missing type for return value" for arg in arg_spec.args + arg_spec.kwonlyargs: assert arg in annotations, ("missing type for parameter '" + arg + "'") @functools.wraps(function) DV1.2 - 16042012

92

Python 3

2012 memIQ def wrapper(*args, **kwargs): for name, arg in (list(zip(arg_spec.args, args)) + list(kwargs.items())): assert isinstance(arg, annotations[name]), ( "expected argument '{0}' of {1} got {2}".format( name, annotations[name], type(arg))) result = function(*args, **kwargs) assert isinstance(result, annotations["return"]), ( "expected return of {0} got {1}".format( annotations["return"], type(result))) return result return wrapper

-

Modul inspect

Acum aplelul: is_unicode_punctuation(("!", "@")) # AssertionError!! Alt motiv de anotare: def func() -> "author=Popescu Ion":

8.2 OOP

8.2.1 Folosirea lui __slots__ class Point: __slots__ = ("x", "y") def __init__(self, x=0, y=0): self.x = x self.y = y In mod obisnuit o instanta foloseste un dictionary privat __dict__ pentru a tine atributele obiectului se pot adauga sau scoate attribute in mod dynamic. Daca se foloseste __slots__ - obiectul nu mai are dictionarul atasat, au doar atributele definite initial, nu se pot adauga/scoate dinamic attribute; sunt mai rapide

8.2.2 Controlul accesului la attribute class Ord: def __getattr__(self, char): return ord(char) ord = Ord() ord.a 97 - Se foloseste builtins.ord(char); import builtins! DV1.2 - 16042012

93

Python 3

2012 memIQ

Exemplu: class Const: def __setattr__(self, name, value): if name in self.__dict__: raise ValueError("cannot change a const attribute") self.__dict__[name] = value def __delattr__(self, name): if name in self.__dict__: raise ValueError("cannot delete a const attribute") raise AttributeError("'{0}' object has no attribute '{1}'" .format(self.__class__.__name__, name)) Folosire: const = Const() const.max = 100

Exemplu: echivalent pentru constant: Const = collections.namedtuple("_", "min max")(191, 591) Const.min, Const.max # returns: (191, 591) Offset = collections.namedtuple("_", "id name description")(*range(3)) Offset.id, Offset.name, Offset.description # returns: (0, 1, 2)

Exemplu: din clasa Image @property def width(self): return self.__width Pentru a trata unitar atributele: def __getattr__(self, name): if name == "colors": return set(self.__colors) # copie classname = self.__class__.__name__ if name in frozenset({"background", "width", "height"}): return self.__dict__["_{classname}__{name}".format( **locals())] # acces direct la atribute raise AttributeError("'{classname}' object has no " "attribute '{name}'".format(**locals()))

8.2.3 Functori Functor – este un obiect care se poate apela ca o functie. In Python – este un obiect functie. DV1.2 - 16042012

94

Python 3

2012 memIQ

O clasa care are metoda speciala __call__() este un functor. Exemplu: strip_punctuation = Strip(",;:.!?") strip_punctuation("Buna ziua!") class Strip: def __init__(self, characters): self.characters = characters def __call__(self, string): return string.strip(self.characters) -

Putem crea oricate obiecte Strip dorim, fiecare cu lista de caractere de scos

Alternativa - folosirea unui closure – o functie ce capteaza o stare (lista de caractere): def make_strip_function(characters): def strip_function(string): return string.strip(characters) return strip_function strip_punctuation = make_strip_function(",;:.!?") strip_punctuation("Buna ziua!")

Exemplu: SortKey.py – class SortKey: def __init__(self, *attribute_names): self.attribute_names = attribute_names def __call__(self, instance): values = [] for attribute_name in self.attribute_names: values.append(getattr(instance, attribute_name)) return values class Person: def __init__(self, forename, surname, email): self.forename = forename self.surname = surname self.email = email Sortare lista de Person – people.sort(key=SortKey(“surname”))

DV1.2 - 16042012

95

Python 3

2012 memIQ

In loc de functor se poate folosi operator.attrgetter(); exemplu: people.sort(key=operator.attrgetter(“surname”, “forename”)) operator.attrgetter() – returneaza o functie closure care cand este apelata pe un obiect returneaza valoarea atributelor specificate la creare.

8.2.4 Manageri de context Asigura ca un code este precedat si urmat de o actiune. Definesc doua metode speciale - __enter__() si __exit__(), with statement Sintaxa: with expression as variable: suite -

expression trebuie sa fie sau se evalueaza la un obiect de tip manager de context as variable – este optional – va referi la ce intoarce __enter__() deoarece se garanteaza apelul lui __exit__() se poate elimina finally

Exemplu: unele tipuri Python sunt manager de context, de ex. obiectele retunate de open(): fh = None try: fh = open(filename) for line in fh: process(line) except EnvironmentError as err: print(err) finally: if fh is not None: fh.close() Echivalent cu: try: with open(filename) as fh: # file object este context manager! for line in fh: process(line) except EnvironmentError as err: print(err) -

daca apare exceptia ea se propaga, dar se inchide fisierul

DV1.2 - 16042012

96

Python 3

2012 memIQ

Exemplu – doua obiecte context manager: try: with open(source) as fin: with open(target, "w") as fout: for line in fin: fout.write(process(line)) except EnvironmentError as err: print(err)

-

folosirea unui singur with: try: with open(source) as fin, open(target, "w") as fout: for line in fin: …

Crearea unui context manager: clasa cu 2 metode - __enter__() si __exit__() Exemplu: operatii atomice; daca nu apare exceptie se aplica toate transformarile, altfel nu se aplica niciuna; folosire: try: with AtomicList(items) as atomic: atomic.append(58289) del atomic[3] atomic[8] = 81738 atomic[index] = 38172 except (AttributeError, IndexError, ValueError) as err: print("no changes applied:", err)

class AtomicList: def __init__(self, alist, shallow_copy=True): self.original = alist self.shallow_copy = shallow_copy def __enter__(self): # val returnata se tine in as varibila! self.modified = (self.original[:] if self.shallow_copy else copy.deepcopy(self.original)) return self.modified def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is None: self.original[:] = self.modified -

exc_type – exception_type;

DV1.2 - 16042012

97

Python 3 -

2012 memIQ

daca exit returneaza True – nu trebuie propagate exceptia, s-a tratat; False (None) – se propaga exceptia!

8.2.5 Descriptori Sunt clase ce ofera controlul accesului pentru atributele altei clase. Orice clasa ce implementeaza metodele special __get__(), __set__() si __delete__() se numeste (si poate fi folosit ca un) descriptor. Functiile builtin property() si classmethod() sunt implementate folosind descriptori. Exemplu: XmlShadow.py – clasa care tine string-uri. Accesul se face prin proprietati; vrem sa putem obtine si versiuni XML – escaped (sa foloseasca pentru caracterele folosite de XML in mod special codificari: < <, & &, etc.). class Product: - Foloseste __slots__ pentru a nu se putea adauga attribute (__dict__) - Attribute clasa name_as_xml si description_as_xml - Folosire: product = Product("Chisel ", "Chisel & cap", 45.25) product.name, product.name_as_xml, product.description_as_xml ('Chisel ', 'Chisel <3cm>', 'Chisel & cap')

class XmlShadow: def __init__(self, attribute_name): self.attribute_name = attribute_name def __get__(self, instance, owner=None): return xml.sax.saxutils.escape(getattr(instance, self.attribute_name)) Folosire cache (nu prea are rost pentru description!): class CachedXmlShadow: def __init__(self, attribute_name): self.attribute_name = attribute_name self.cache = {} def __get__(self, instance, owner=None): xml_text = self.cache.get(id(instance)) if xml_text is not None: return xml_text return self.cache.setdefault(id(instance), xml.sax.saxutils.escape( getattr(instance, self.attribute_name)))

DV1.2 - 16042012

98

Python 3

2012 memIQ

Exemplu: folosirea descriptor pentru a tine toate proprietatile – vezi ExternalStorage.py class Point: __slots__ = () x = ExternalStorage("x") y = ExternalStorage("y") def __init__(self, x=0, y=0): self.x = x self.y = y self.x = x

descriptor cu numele “x”, se apeleaza __set__() pe el!

class ExternalStorage: __slots__ = ("attribute_name",) __storage = {} def __init__(self, attribute_name): self.attribute_name = attribute_name def __set__(self, instance, value): self.__storage[id(instance), self.attribute_name] = value def __get__(self, instance, owner=None): if instance is None: return self # acces la x din Point return self.__storage[id(instance), self.attribute_name]

Exemplu: descriptor Property ce se comporta ca fi functia builtin property() – vezi sursa Property.py Aplicam la: class NameAndExtension: def __init__(self, name, extension): self.__name = name self.__extension = extension @Property # Uses the custom Property descriptor def name(self): return self.__name @Property # Uses the custom Property descriptor def extension(self): return self.__extension @extension.setter # Uses the custom Property descriptor def extension(self, extension): self.__extension = extension DV1.2 - 16042012

99

Python 3

2012 memIQ

class Property: def __init__(self, getter, setter=None): self.__getter = getter self.__setter = setter self.__name__ = getter.__name__ def __get__(self, instance, owner=None): if instance is None: return self return self.__getter(instance) def __set__(self, instance, value): if self.__setter is None: raise AttributeError("'{0}' is read-only".format( self.__name__)) return self.__setter(instance, value) def setter(self, setter): self.__setter = setter return self

8.2.6 Decoratori de clase Similar cu decoratorii de functii sau metode. Decoratorii de clase primesc un obiect clasa (rezultatul declaratiei class) si returneaza o clasa - o versiune modificata. Exemplu: SortedListDelegate.py (pleaca de la SortedList.py – cap. 6) @Util.delegate("__list", ("pop", "__delitem__", "__getitem__", "__iter__", "__reversed__", "__len__", "__str__")) class SortedList: Implementare decoratorului clasei din Util.py: def delegate(attribute_name, method_names): def decorator(cls): nonlocal attribute_name if attribute_name.startswith("__"): attribute_name = "_" + cls.__name__ + attribute_name for name in method_names: setattr(cls, name, eval("lambda self, *a, **kw: " "self.{0}.{1}(*a, **kw)".format( attribute_name, name))) return cls return decorator DV1.2 - 16042012

100

Python 3

2012 memIQ

Exemplu: FuzzyBool din cap.6 – am furnizat doar metodele special __lt__() si __eq__() corespunzatoare operatorilor < si ==, celelate metode special s-au generat automat. Python produce > pe baza = pe baza >>class Bad(metaclass=Meta.LoadableSaveable): ... def some_method(self): pass Traceback (most recent call last): ... AssertionError: class 'Bad' must provide a load() method >>> class Good(metaclass=Meta.LoadableSaveable): ... def load(self): pass ... def save(self): pass >>> g = Good()

Metaclasa poate sa modifice clasele ce o folosesc (nume, clasele parinte, dictionarul clasei create); de ex. alternativa la decoratorii @property si @name.setter sunt conventii de nume pentru a identifica proprietatile: daca clasa are metode de forma get_name() si set_name() vom avea si o data private __name accesata prin proprietatea instanta.name: class Product(metaclass=AutoSlotProperties): def __init__(self, barcode, description): self.__barcode = barcode self.description = description DV1.2 - 16042012

105

Python 3

2012 memIQ def get_barcode(self): return self.__barcode def get_description(self): return self.__description def set_description(self, description): if description is None or len(description) < 3: self.__description = "" else: self.__description = description

>>> product = Product("101110110", "8mm Stapler") >>> product.barcode, product.description ('101110110', '8mm Stapler') -

dir(Product)

barcode, description; au disparut get_name() si set_name()!

class AutoSlotProperties(type): def __new__(mcl, classname, bases, dictionary): slots = list(dictionary.get("__slots__", [])) for getter_name in [key for key in dictionary if key.startswith("get_")]: if isinstance(dictionary[getter_name], collections.Callable): name = getter_name[4:] slots.append("__" + name) getter = dictionary.pop(getter_name) setter_name = "set_" + name setter = dictionary.get(setter_name, None) if (setter is not None and isinstance(setter, collections.Callable)): del dictionary[setter_name] dictionary[name] = property(getter, setter) dictionary["__slots__"] = tuple(slots) return super().__new__(mcl, classname, bases, dictionary)

8.3 Programare functionala Mapare list(map(lambda x: x ** 2, [1, 2, 3, 4])) -

Returneaza un iterator

[x **2 for x in [1,2,3,4]] - list comprehension (x **2 for x in [1,2,3,4]) - generator

DV1.2 - 16042012

106

Python 3

2012 memIQ

Filtrare list(filter(lambda x: x > 0, [1, -3, 4, -6])) [x for x in [1, -3, 4, -6] if x > 0] (x for x in [1, -3, 4, -6] if x > 0)

Reducere – produce o singura valoare functools.reduce(lambda x, y: x * y, [1,2,3,4]) functools.reduce(operator.mul, [1,2,3,4]) Functii built-in ce primesc un iterabil: - all() - any() - max() - min() - sum() Exemple: functools.reduce(operator.add, (os.path.getsize(x) for x in files)) functools.reduce(operator.add, map(os.path.getsize, files)) functools.reduce(operator.add, map(os.path.getsize, filter(lambda x: x.endswith(".py"), files))) functools.reduce(operator.add, map(os.path.getsize, (x for x in files if x.endswith(".py")))) functools.reduce(operator.add, (os.path.getsize(x) for x in files if x.endswith(".py"))) sum(os.path.getsize(x) for x in files if x.endswith(".py"))

Modulul operator (pe langa operatori): - operator.attrgetter() - operator.itemgetter() Returneaza functii (vezi documentatia) care pot fi folosite sa extraga atributele sau elementele specificate operator.itemgetter(1, 3, 5)(L) – elementele din L de index 1, 3, 5 Functia returnata se poate folosi in map(), filter(), functools.reduce() sau in list, dict sau set comprehension L.sort(key = operator.attrgetter(“priority”)) DV1.2 - 16042012

107

Python 3

2012 memIQ

Key – se poate folosi o functie, metoda, o functie lambda, sau operator.attrgetter()

Modulul itertools for value in itertools.chain(data_list1, data_list2, data_list3): total += value

8.3.1 Functii partiale Crearea unei functii din una existent si argumente care face ce face functia originala dar cu argumente fixe. enumerate1 = functools.partial(enumerate, start=1) for lino, line in enumerate1(lines): process_line(i, line) Exemplu: reader = functools.partial(open, mode="rt", encoding="utf8") writer = functools.partial(open, mode="wt", encoding="utf8") reader(filename) writer(filename)

loadButton = tkinter.Button(frame, text="Load", command=functools.partial(doAction, "load")) saveButton = tkinter.Button(frame, text="Save", command=functools.partial(doAction, "save"))

8.4 Exemplu Vezi Valid.py Problema: validarea atributelor Se poate face individual prin proprietati (sau functii getter si setter); se poate face o validarea la nivel de clasa: @valid_string("name", empty_allowed=False) @valid_string("productid", empty_allowed=False, regex=re.compile(r"[A-Z]{3}\d{4}")) @valid_string("category", empty_allowed=False, acceptable= frozenset(["Consumables", "Hardware", "Software", "Media"])) @valid_number("price", minimum=0, maximum=1e6) @valid_number("quantity", minimum=1, maximum=1000) DV1.2 - 16042012

108

Python 3

2012 memIQ

class StockItem: def __init__(self, name, productid, category, price, quantity): self.name = name self.productid = productid self.category = category self.price = price self.quantity = quantity Validarea se face combinand decoratorii de clasa cu descriptorii. def valid_string(attr_name, empty_allowed=True, regex=None, acceptable=None): def decorator(cls): name = "__" + attr_name def getter(self): return getattr(self, name) def setter(self, value): assert isinstance(value, str), (attr_name + " must be a string") if not empty_allowed and not value: raise ValueError("{0} may not be empty".format( attr_name)) if ((acceptable is not None and value not in acceptable) or (regex is not None and not regex.match(value))): raise ValueError("{attr_name} cannot be set to " "{value}".format(**locals())) setattr(self, name, value) setattr(cls, attr_name, GenericDescriptor(getter, setter)) return cls return decorator

class GenericDescriptor: def __init__(self, getter, setter): self.getter = getter self.setter = setter def __get__(self, instance, owner=None): if instance is None: return self return self.getter(instance) def __set__(self, instance, value): return self.setter(instance, value)

DV1.2 - 16042012

109

Python 3

2012 memIQ

9 Procese și fire de execuție Concurență la nivel de: - Procese – procesoare multicore - Fire de execuție

9.1 Modulul subprocess Este folositor când dorim sa lansăm programe existente (la care putem pasa parametrii în linia de comandă), cu care eventual comunicăm prin pipes. Exemplu: grep care cauta un cuvânt în fișierele specificate în linia de comandă; se caută recursiv și în subdirectori; căutarea se deleagă la oricâte procese dorim. Vezi exemplele: grepword-p.py, grepword-p-child.py Documentație modul: http://docs.python.org/py3k/library/subprocess.html

9.2 Modulul threading -

Problema accesului la resurse comune – race condition mecanism de acces exclusiv deadlock crearea thread-urilor – similar Java: o subclasarea threading.Thread o parsarea unui obiect callable la threading.Thread

Exemplu: similar cu exemplul anterior, folosește thread-uri în loc de lansarea de procese – vezi grepword-t.py - queue.Queue – este thread safe (vezi modulul queue: LifoQueue, PriorityQueue)

9.3 Modulul multiprocessing Varianta ce folosește modulul multiprocessing: grepword-m.py

9.4 Exemplu Găsirea de fișiere duplicat: se compară numele și mărimea fișierelor, pentru m – vezi findduplicates-t.py Pachet threading: Lock, RLock, Semaphore, Condition Temă: modificați programul findduplicates-t.py pentru a afișa în ordine descrescătoare fișierele duplicat găsite.

DV1.2 - 16042012

110

Python 3

2012 memIQ

10 Lucrul în rețea – networking Comunicare între programe; soluții client – server. Clientul trebuie știe să să găsească serverul – adresa IP (Internet Protocol) și numărul portului + protocol de comunicare comun. Modulul sockets: - suportă adrese IPv4 și IPv6 - UDP (User Datagram Protocol) - TCP (Transmission Control Protocol) – orientat stream - FTP (File Transfer Protocol) și HTTP (Hypertext Transfer Protocol) sunt bazate pe TCP

10.1 Exemplu Aplicație de gestiune mașini. Client – car_registration.py Server – car_registration_server.py Note: • Context manager - SocketManager • struct.Struct("!I") – vezi modulul struct o ! - byte order = big-endian (nework) o I – unsigned int • Modulul socketserver – bazat pe sockets • contextlib.closing – context manager, se apeleaza close() • socketserver.ForkingMixIn – multi – procese • socketserver.ThreadingMixIn – multi – threading • TCPServer, UDPServer, UnixStreamServer, UnixDatagramServer • RequestHandler.Cars – variabilă clasă (la fel ca și Call) Temă: modificați exemplul (client + server) pentru a include o nouă operație: GET_LICENSES_STARTING_WITH ce afișează toate plăcuțele de înmatriculare ce încep cu stringul dat.

DV1.2 - 16042012

111

Python 3

2012 memIQ

11 Baze de date SQL – Structured Query Language – API pentru lucrul cu baze de date relaționale SQLite 3 – standard pentru Python Tipuri de Database Manager (DBM) • ține informația în formă de perechi cheie – valoare • Python oferă interfețe pentru DBM standard • Funcționează ca dicționare ce sunt ținute pe disc • Modulul shelve permite chei de tip string și valori orice obiect (pickable) Pachete pentru interfațare cu orice bază de date – vezi http://pypi.python.org/pypi/ ORM – Object Relational Mapper – layer între o bază de date relațională și obiecte Python: - SQLAlchemy – www.sqlalchemy.org - SQLObject – www.sqlobject.org Exemplu: aplicație pentru gestiunea unei colecții de DVD-uri

11.1 Baze de date DBM Modul shelve - oferă un wrapper pentru a lucra cu un DBM ca și cu un dicționar - cheile sunt stringuri, valorile obiecte pickable; acestea se transformă în bytes - Fișierele DBM pot să nu fie compatibile între sisteme diferite; se poate folisi formatul XML pentru transfer de date între fișiere DBM diferite - Lucrul similar cu un dicționar; open() și sync() Vezi: dvds-dbm.py

11.2 Baze de date SQL Modul sqlite3 Vezi dvds-sql.py Tabele: - dvds – id, title, year, duration, director_id - directors: id, name API: - db.close() - db.commit() - db.cursor() – returnează un obiect cursor prin care executăm operații asupra db - db.rollback()

DV1.2 - 16042012

112

Python 3

2012 memIQ

Temă: oferiți suport pentru serverul din cap. Anterior, informația să fie ținută într-o BD, fie folosind modulul shelve, fie modulul sqlite3.

DV1.2 - 16042012

113

Python 3

2012 memIQ

12 Referințe http://code.google.com/edu/languages/google-python-class/ http://www.itmaybeahack.com/homepage/books/python.html

DV1.2 - 16042012

114

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF