Arxius

Python: característiques interessants

Escrit al 2007-07-27 22:39:42 per cpina

Python és un llenguatge de programació molt entenedor, però que a la vegada té característiques que el fan molt interessant.


A vegades un es pot quedar amb la part més superficial del llenguatge. De fet, amb aquesta part, ja es pot fer tot, però convé tenir a mà "més potència" ja sigui per fer tasques de forma més fàcil com per entendre codi d'altra gent.


Aquí es fa una petita enumeració de característiques/sintaxis que no són molt naturals de llegir, o que podem desconèixer que Python té això.

Python és un llenguatge de programació molt entenedor, però que a la vegada té característiques que el fan molt interessant.
A vegades un es pot quedar amb la part més superficial del llenguatge. De fet, amb aquesta part, ja es pot fer tot, però convé tenir a mà "més potència" ja sigui per fer tasques de forma més fàcil com per entendre codi d'altra gent.

Aquí es fa una petita enumeració de característiques/sintaxis que no són molt naturals de llegir, o que podem desconèixer que Python té això.

map

Igual que Lisp: executa una funció sobre cada element de la llista.
>>> import math
>>> l=[1,2,3,4,5,6]
>>> map(math.sqrt,l)


O un altre exemple:
>>> import string
>>> a=["hola  ","   bon dia   "]
>>> map(string.strip,a)
['hola', 'bon dia']

(aplica una funció sobre cada element de la llista)

yield

Retorna el valor, però es pot seguir executant la funció amb .next()
#!/usr/bin/python

def comptador():
    i=0

    for i in xrange(5):
        print "Abans yield"
        yield i*i
        print "Despres yield"

a=comptador()
print a.next()
print a.next()
print a.next()
print a.next()
print a.next()

Manté l'estat de les variables. és el què fa servir, per exemple, xrange (range retorna una llista i punt, xrange retorna element a element i és molt més òptim per fer coses tipus for i in xrange(1,100)

<H2>Comprehension lists</H2>
(http://www.secnetix.de/~olli/Python/list_comprehensions.hawk)

Bàsicament: executa un bucle sobre una llista, permet posar una condició if i fer operacions sobre l'element que retorna de la llista. Retorna una nova llista.

Exemple 1:
>>> V = [2**i for i in xrange(13)]
>>> M = [x for x in xrange(10) if x % 2 == 0]
>>> print V
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]
>>> print M
[0, 2, 4, 6, 8]


També pot ser una mica més embolicat:
>>> V = [(2**i,i) for i in xrange(13)]
>>> print V
[(1, 0), (2, 1), (4, 2), (8, 3), (16, 4), (32, 5), (64, 6), (128, 7), (256, 8), (512, 9), (1024, 10), (2048, 11), (4096, 12)]


Closures

Recomano llegir almenys el primer paràgraf, per entendre què són les closures:
http://en.wikipedia.org/wiki/Closure_(computer_science)

També és força interessant la discusió:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/67618

Una petita explicació: les closures són quan una funció pot accedir a l'entorn (variables, objectes, etc.) de la funció que el crida. Mal utilitzat pot ser molt dolent: trenca les regles bàsiques d'encapsulació de la programació imperativa i de la programació orientada a objectes. Per això jo no recomanaria, en general, fer-les servir.

Les closures tenen un moment que són molt famoses (segurament perquè estan molt al dia a Ruby). Però les closures aporten poc respecte a tenir una classe. Podem llegir-ne opinions a aquest <A href="http://listas.aditel.org/archivos/python-es/2007-July/022870.html">email</A>, o bé <A href="http://listas.aditel.org/archivos/python-es/2007-July/022872.html">aquest.</A>

Tinc pendent de donar-hi algunes voltes més.

Decorators

(http://technofreakatchennai.wordpress.com/2007/03/08/decorators-in-python/)

Inicialment permeten una cosa força simple: afegir, a algunes funcions, un codi previ i posterior a la crida de la funció. Però permet, evidentment, que el codi "previ" i "posterior" sigui fàcil de posar i treure. El codi és codi Python normal i pot modificar paràmetres, el codi en sí mateix, fer logs, etc. qualsevol cosa.

És com un wrapper, però permet posar varis decoradors apilats. També és possible fer-ho a classes: així enlloc de tenir N classes heredant d'altres classes per tenir totes les combinacions necessaries només cal afegir decoradors.
#!/usr/bin/python

def NomDecorador(fn): #Rep el nom de la funcio que se li passa
    def _inner(x): #Es crida amb el primer parametre que se li havia passat
        print "Has cridat amb parametre %d pero el crido amb %d" %(x,x+1)
        fn(x+1)
        print "Codi despres de la funcio"
    return _inner

@NomDecorador
def myfunc(x):
    print "I got", x

myfunc(5)


Convertir una tupla a arguments

L'operador * ens permet convertir una tupla a diferents paràmetres a la crida d'una funció, o rebre N paràmetres.
#!/usr/bin/python

def rebre(primer,*altres):
    print "Primer",primer
    for i in altres:
        print "Opc:",i

rebre(1,2,5,2)
rebre(1,*(6,8,5,2)) #com si fos rebre(1,6,8,5,2)

Veure com l'exemple és doble :-) (i per tant poc pedagògic): per un costat tenim l'operador "*" per rebre N elements (a la línia "def rebre") i per l'altre costat tenim com enviar la tupla com si fossin arguments normals, veure última línia.

Categories: Articles


Comentaris

  • Sense comentaris
Arxius