Python 3_V1.2.pdf
May 5, 2017 | Author: mihaineag91 | Category: N/A
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