Rendez votre code Python plus beau !

Preview:

DESCRIPTION

Présentation à PyCon FR à Strabsourg le 25 octobre 2013.

Citation preview

Rendez votre code Python plus beau !

Ronan Amicel @amicel

PyCon FR – 25 octobre 2013 – Strasbourg

Ronan Amicel

Founder @ PocketSensei !

Hacker in Residence @ TheFamily

Version originale

Raymond Hettinger !

PyCon US 2013 !

Vidéo sur pyvideo.org

Du code plus beau ?

Du code plus beau ?

• plus simple

Du code plus beau ?

• plus simple

• plus concis

Du code plus beau ?

• plus simple

• plus concis

• plus clair

Du code plus beau ?

• plus simple

• plus concis

• plus clair

• plus idiomatique (== plus « pythonique »)

Du code plus beau ?

• plus simple

• plus concis

• plus clair

• plus idiomatique (== plus « pythonique »)

• plus performant

Itérations

Itérer sur un intervalle d’entiers

Itérer sur un intervalle d’entiers

for i in [0, 1, 2, 3, 4, 5]:! print i**2

Itérer sur un intervalle d’entiers

for i in range(6):! print i**2

for i in [0, 1, 2, 3, 4, 5]:! print i**2

Itérer sur un intervalle d’entiers

for i in range(6):! print i**2

for i in [0, 1, 2, 3, 4, 5]:! print i**2

for i in xrange(6):! print i**2

Itérer sur une collection d'objets

Itérer sur une collection d'objets

plats = ['choucroute', 'munster', 'kouglof']

Itérer sur une collection d'objets

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)):! print plats[i]

Itérer sur une collection d'objets

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)):! print plats[i]

for plat in plats:! print plat

Itérer en partant de la fin

Itérer en partant de la fin

plats = ['choucroute', 'munster', 'kouglof']

Itérer en partant de la fin

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)-1, -1, -1):! print plats[i]

Itérer en partant de la fin

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)-1, -1, -1):! print plats[i]

for plat in reversed(plats):! print plat

Itérer en maintenant un indice

Itérer en maintenant un indice

plats = ['choucroute', 'munster', 'kouglof']

Itérer en maintenant un indice

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)):! print i, '-->', plats[i]

Itérer en maintenant un indice

plats = ['choucroute', 'munster', 'kouglof']

for i in range(len(plats)):! print i, '-->', plats[i]

for i, plat in enumerate(plats):! print i, '-->', plat

Itérer sur deux collections en même temps

Itérer sur deux collections en même temps

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

Itérer sur deux collections en même temps

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

n = min(len(vins), len(plats))!for i in range(n):! print vins[i], '-->', plats[i]

Itérer sur deux collections en même temps

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

n = min(len(vins), len(plats))!for i in range(n):! print vins[i], '-->', plats[i]

for name, plat in zip(vins, plats):! print name, '-->', plat

Itérer sur deux collections en même temps

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

n = min(len(vins), len(plats))!for i in range(n):! print vins[i], '-->', plats[i]

for name, plat in zip(vins, plats):! print name, '-->', plat

for name, plat in izip(vins, plats):! print name, '-->', plat

Itérer sur deux collections en même temps

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

n = min(len(vins), len(plats))!for i in range(n):! print vins[i], '-->', plats[i]

for name, plat in zip(vins, plats):! print name, '-->', plat

for name, plat in izip(vins, plats):! print name, '-->', plat

from itertools import izip

Itérer selon un ordre de tri

Itérer selon un ordre de tri

plats = ['choucroute', 'munster', 'kouglof']

Itérer selon un ordre de tri

plats = ['choucroute', 'munster', 'kouglof']

for plat in sorted(plats):! print plat

Itérer selon un ordre de tri

plats = ['choucroute', 'munster', 'kouglof']

for plat in sorted(plats):! print plat

for plat in sorted(plats, reverse=True):! print plat

Trier selon un critère particulier

Trier selon un critère particulier

plats = ['choucroute', 'munster', 'kouglof']

Trier selon un critère particulier

plats = ['choucroute', 'munster', 'kouglof']

def compare_length(c1, c2):! if len(c1) < len(c2):! return -1! if len(c1) > len(c2):! return 1! return 0!!print sorted(plats, cmp=compare_length)

Trier selon un critère particulier

plats = ['choucroute', 'munster', 'kouglof']

def compare_length(c1, c2):! if len(c1) < len(c2):! return -1! if len(c1) > len(c2):! return 1! return 0!!print sorted(plats, cmp=compare_length)

print sorted(plats, key=len)

Dictionnaires

Itérer sur les clésd'un dictionnaire

Itérer sur les clésd'un dictionnaire

d = {! 'gewurztraminer': ‘kouglof',! 'edelzwicker': ‘munster',! 'riesling': ‘choucroute’,!}

Itérer sur les clésd'un dictionnaire

d = {! 'gewurztraminer': ‘kouglof',! 'edelzwicker': ‘munster',! 'riesling': ‘choucroute’,!}

for key in d:! print key

Itérer sur les clésd'un dictionnaire

d = {! 'gewurztraminer': ‘kouglof',! 'edelzwicker': ‘munster',! 'riesling': ‘choucroute’,!}

for key in d:! print key

d = {key: d[key] for key in d if not key.startswith('r')}

Itérer sur les clés et les valeurs d'un dictionnaire

Itérer sur les clés et les valeurs d'un dictionnaire

for key in d:! print key, '-->', d[key]

Itérer sur les clés et les valeurs d'un dictionnaire

for key in d:! print key, '-->', d[key]

for key, value in d.items():! print key, '-->', value

Itérer sur les clés et les valeurs d'un dictionnaire

for key in d:! print key, '-->', d[key]

for key, value in d.items():! print key, '-->', value

for key, value in d.iteritems():! print key, '-->', value

Construire un dictionnaire à partir de paires

Construire un dictionnaire à partir de paires

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

Construire un dictionnaire à partir de paires

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

d = dict(izip(vins, plats))!{'gewurztraminer': 'kouglof', 'edelzwicker': ‘munster',! 'riesling': 'choucroute'}

Construire un dictionnaire à partir de paires

vins = ['riesling', 'edelzwicker', 'gewurztraminer']!plats = ['choucroute', 'munster', 'kouglof']

d = dict(izip(vins, plats))!{'gewurztraminer': 'kouglof', 'edelzwicker': ‘munster',! 'riesling': 'choucroute'}

d = dict(enumerate(vins))!{0: 'riesling', 1: 'edelzwicker', 2: 'gewurztraminer'}

Compter avec des dictionnaires

Compter avec des dictionnaires

plats = ['choucroute', 'munster', 'choucroute', ‘kouglof',! 'munster', 'choucroute']

Compter avec des dictionnaires

plats = ['choucroute', 'munster', 'choucroute', ‘kouglof',! 'munster', 'choucroute']

d = {}!for plat in plats:! if plat not in d:! d[plat] = 0! d[plat] += 1!{'kouglof': 1, 'munster': 2, 'choucroute': 3}

Compter avec des dictionnaires

plats = ['choucroute', 'munster', 'choucroute', ‘kouglof',! 'munster', 'choucroute']

d = {}!for plat in plats:! if plat not in d:! d[plat] = 0! d[plat] += 1!{'kouglof': 1, 'munster': 2, 'choucroute': 3}

d = defaultdict(int)!for plat in plats:! d[plat] += 1

Clarifier

Clarifier les appels de fonctions avec des arguments mots-clés

search(‘#pyconfr', False, 20, True)

Clarifier les appels de fonctions avec des arguments mots-clés

search(‘#pyconfr', False, 20, True)

search(‘#pyconfr', retweets=False, numtweets=20, popular=True)

Clarifier les appels de fonctions avec des arguments mots-clés

Clarifier les valeurs de retour multiples avec des tuples nommés

Clarifier les valeurs de retour multiples avec des tuples nommés

doctest.testmod()!(0, 4)

Clarifier les valeurs de retour multiples avec des tuples nommés

doctest.testmod()!(0, 4)

doctest.testmod()!TestResults(failed=0, attempted=4)

Clarifier les valeurs de retour multiples avec des tuples nommés

doctest.testmod()!(0, 4)

doctest.testmod()!TestResults(failed=0, attempted=4)

from collections import namedtuple!TestResults = namedtuple('TestResults', ['failed', 'attempted'])

« Unpacking »de séquences

« Unpacking »de séquences

p = 'Ronan', 'Amicel', 37, '@amicel'

« Unpacking »de séquences

p = 'Ronan', 'Amicel', 37, '@amicel'

prenom = p[0]!nom = p[1]!age = p[2]!twitter = p[3]

« Unpacking »de séquences

p = 'Ronan', 'Amicel', 37, '@amicel'

prenom = p[0]!nom = p[1]!age = p[2]!twitter = p[3]

prenom, nom, age, twitter = p

Performance

Concaténer des chaînes

Concaténer des chaînes

vins = ['riesling', 'edelzwicker', 'gewurztraminer',! 'pinot noir', 'pinot gris', 'muscat', 'sylvaner']

Concaténer des chaînes

vins = ['riesling', 'edelzwicker', 'gewurztraminer',! 'pinot noir', 'pinot gris', 'muscat', 'sylvaner']

s = vins[0]!for name in vins[1:]:! s += ', ' + name!print s

Concaténer des chaînes

vins = ['riesling', 'edelzwicker', 'gewurztraminer',! 'pinot noir', 'pinot gris', 'muscat', 'sylvaner']

s = vins[0]!for name in vins[1:]:! s += ', ' + name!print s

print ', '.join(vins)

Décorateurs etcontext managers

Utiliser des décorateurs pour factoriser de la logique

Utiliser des décorateurs pour factoriser de la logique

def web_lookup(url, saved={}):! if url in saved:! return saved[url]! page = urllib.urlopen(url).read()! saved[url] = page! return page

Utiliser des décorateurs pour factoriser de la logique

def web_lookup(url, saved={}):! if url in saved:! return saved[url]! page = urllib.urlopen(url).read()! saved[url] = page! return page

@cache!def web_lookup(url):! return urllib.urlopen(url).read()

Décorateur cache

def cache(func):! saved = {}!! @wraps(func)! def newfunc(*args):! if args in saved:! return newfunc(*args)! result = func(*args)! saved[args] = result! return result!! return newfunc

Ouvrir et fermer des fichiers

Ouvrir et fermer des fichiers

f = open('data.txt')!try:! data = f.read()!finally:! f.close()

Ouvrir et fermer des fichiers

f = open('data.txt')!try:! data = f.read()!finally:! f.close()

with open('data.txt') as f:! data = f.read()

Utiliser des locks (verrous)

Utiliser des locks (verrous)

# Créer un lock!lock = threading.Lock()

Utiliser des locks (verrous)

# Créer un lock!lock = threading.Lock()

# Utiliser un lock (ancienne méthode)!lock.acquire()!try:! print 'Critical section 1'! print 'Critical section 2'!finally:! lock.release()

Utiliser des locks (verrous)

# Créer un lock!lock = threading.Lock()

# Utiliser un lock (ancienne méthode)!lock.acquire()!try:! print 'Critical section 1'! print 'Critical section 2'!finally:! lock.release()

# Utiliser un lock (nouvelle méthode)!with lock:! print 'Critical section 1'! print 'Critical section 2'

« One liners »

Listes en compréhension et expressions génératrices

Listes en compréhension et expressions génératrices

result = []!for i in range(10):! s = i ** 2! result.append(s)!print sum(result)

Listes en compréhension et expressions génératrices

result = []!for i in range(10):! s = i ** 2! result.append(s)!print sum(result)

print sum([i**2 for i in xrange(10)])

Listes en compréhension et expressions génératrices

result = []!for i in range(10):! s = i ** 2! result.append(s)!print sum(result)

print sum([i**2 for i in xrange(10)])

print sum(i**2 for i in xrange(10))

Questions ?

Merci !

Recommended