web-dev-qa-db-fra.com

Extraits de python courts (et utiles)

Dans l’esprit du "quel est votre extrait de code C/C++ le plus utile" - thread:

Avez-vous les gars (souvent) des extraits de Python monofonctionnels que vous utilisez (souvent) et que vous souhaitez partager avec la communauté StackOverlow? Veuillez garder les entrées petites (moins de 25 lignes .__ peut-être?) Et ne donner qu'un exemple par poste.

Je commencerai par un court extrait que j'utilise de temps en temps pour compter les sloc (lignes de code source) dans les projets Python:

# prints recursive count of lines of python source code from current directory
# includes an ignore_list. also prints total sloc

import os
cur_path = os.getcwd()
ignore_set = set(["__init__.py", "count_sourcelines.py"])

loclist = []

for pydir, _, pyfiles in os.walk(cur_path):
    for pyfile in pyfiles:
        if pyfile.endswith(".py") and pyfile not in ignore_set:
            totalpath = os.path.join(pydir, pyfile)
            loclist.append( ( len(open(totalpath, "r").read().splitlines()),
                               totalpath.split(cur_path)[1]) )

for linenumbercount, filename in loclist: 
    print "%05d lines in %s" % (linenumbercount, filename)

print "\nTotal: %s lines (%s)" %(sum([x[0] for x in loclist]), cur_path)
45
ChristopheD

Initialiser une liste 2D

Bien que cela puisse être fait en toute sécurité pour initialiser une liste:

lst = [0] * 3

Le même truc ne fonctionnera pas pour une liste 2D (liste de listes):

>>> lst_2d = [[0] * 3] * 3
>>> lst_2d
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> lst_2d[0][0] = 5
>>> lst_2d
[[5, 0, 0], [5, 0, 0], [5, 0, 0]]

L'opérateur * duplique ses opérandes et les listes dupliquées construites avec [] pointent sur la même liste. La bonne façon de faire est:

>>> lst_2d = [[0] * 3 for i in xrange(3)]
>>> lst_2d
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> lst_2d[0][0] = 5
>>> lst_2d
[[5, 0, 0], [0, 0, 0], [0, 0, 0]]
21
Eli Bendersky

J'aime utiliser any et un générateur:

if any(pred(x.item) for x in sequence):
    ...

au lieu d'un code écrit comme ceci:

found = False
for x in sequence:
    if pred(x.n):
        found = True
if found:
    ...

J'ai d'abord appris cette technique d'un article de Peter Norvig article .

34
Jacob Gabrielson

Le seul "truc" que je connaisse qui m'a vraiment séduit quand j'ai appris qu'il s'agissait d'énumérer. Il vous permet d’avoir accès aux index des éléments d’une boucle for.

>>> l = ['a','b','c','d','e','f']
>>> for (index,value) in enumerate(l):
...     print index, value
... 
0 a
1 b
2 c
3 d
4 e
5 f
21
theycallmemorty

Zip(*iterable) transpose un itérable.

>>> a=[[1,2,3],[4,5,6]]
>>> Zip(*a)
    [(1, 4), (2, 5), (3, 6)]

C'est aussi utile avec les dict.

>>> d={"a":1,"b":2,"c":3}
>>> Zip(*d.iteritems())
[('a', 'c', 'b'), (1, 3, 2)]
15
AKX

Lancez un simple serveur Web pour les fichiers du répertoire en cours:

python -m SimpleHTTPServer

Utile pour partager des fichiers.

14
Adam Lehenbauer

Une "barre de progression" qui ressemble à:

|#############################---------------------|
59 percent done

Code:

class ProgressBar():
    def __init__(self, width=50):
        self.pointer = 0
        self.width = width

    def __call__(self,x):
         # x in percent
         self.pointer = int(self.width*(x/100.0))
         return "|" + "#"*self.pointer + "-"*(self.width-self.pointer)+\
                "|\n %d percent done" % int(x) 

Fonction de test (pour le système Windows, remplacez "clear" par "CLS"):

if __== '__main__':
    import time, os
    pb = ProgressBar()
    for i in range(101):
        os.system('clear')
        print pb(i)
        time.sleep(0.1)
11
Theodor

Pour aplatir une liste de listes, telles que

[['a', 'b'], ['c'], ['d', 'e', 'f']]

dans

['a', 'b', 'c', 'd', 'e', 'f']

utilisation

[inner
    for outer in the_list
        for inner in outer]
11
George V. Reilly

Grande accélération pour la liste imbriquée et les dictionnaires avec:

deepcopy = lambda x: cPickle.loads(cPickle.dumps(x))
10
vartec

Supposons que vous ayez une liste d'éléments et que vous souhaitiez un dictionnaire avec ces éléments comme clés. Utilisez des clés:

>>> items = ['a', 'b', 'c', 'd']
>>> idict = dict().fromkeys(items, 0)
>>> idict
{'a': 0, 'c': 0, 'b': 0, 'd': 0}
>>>

Le deuxième argument de fromkeys est la valeur à attribuer à toutes les clés nouvellement créées.

8
Eli Bendersky

Pour savoir si la ligne est vide (c'est-à-dire si la taille est 0 ou ne contient que des espaces), utilisez la bandelette de méthode de chaîne dans une condition, comme suit:

if not line.strip():    # if line is empty
    continue            # skip it
7
Eli Bendersky

J'aime celui-ci pour tout compresser dans un répertoire. Hotkey it pour instabackups!

import zipfile

z = zipfile.ZipFile('my-archive.Zip', 'w', zipfile.Zip_DEFLATED)
startdir = "/home/johnf"
for dirpath, dirnames, filenames in os.walk(startdir):
  for filename in filenames:
    z.write(os.path.join(dirpath, filename))
z.close()
5
John Feminella

Pour les compréhensions de liste nécessitant une mise à jour, ensuite:

[fun(curr,next) 
 for curr,next 
 in Zip(list,list[1:].append(None)) 
 if condition(curr,next)] 

Pour la liste circulaire Zip(list,list[1:].append(list[0])).

Pour précédent, actuel: Zip([None].extend(list[:-1]),list) circular: Zip([list[-1]].extend(list[:-1]),list)

4
vartec

Fichiers Hardlink identiques dans le répertoire en cours (sous Unix, cela signifie qu'ils ont un stockage physique partagé, ce qui signifie beaucoup moins d'espace):

import os
import hashlib

dupes = {}

for path, dirs, files in os.walk(os.getcwd()):
    for file in files:
        filename = os.path.join(path, file)
        hash = hashlib.sha1(open(filename).read()).hexdigest()
        if hash in dupes:
            print 'linking "%s" -> "%s"' % (dupes[hash], filename)
            os.rename(filename, filename + '.bak')
            try:
                os.link(dupes[hash], filename)
                os.unlink(filename + '.bak')
            except:
                os.rename(filename + '.bak', filename)
            finally:
        else:
            dupes[hash] = filename
4
rmmh

En voici quelques-unes qui, à mon avis, méritent d’être connues mais qui pourraient ne pas être utiles au quotidien . La plupart d’entre elles sont une seule ligne.

Supprimer les doublons d'une liste

L = list(set(L))

Obtenir les entiers d'une chaîne (espace séparé)

ints = [int(x) for x in S.split()]

Trouver Factorial

fac=lambda(n):reduce(int.__mul__,range(1,n+1),1)

Trouver le plus grand commun diviseur

>>> def gcd(a,b):
...     while(b):a,b=b,a%b
...     return a
3
jack_carver
  • comme une autre personne ci-dessus, j'ai dit 'Wooww !!' quand j'ai découvert enumerate ()

  • J'ai chanté un éloge à Python quand j'ai découvert repr () qui m'a donné la possibilité de voir précisément le contenu des chaînes que je voulais analyser avec une regex

  • J'étais très satisfait de découvrir que print '\n'.join(list_of_strings) est affiché beaucoup plus rapidement avec '\ n'.join (...) que for ch in list_of_strings: print ch

  • splitlines (1) avec un argument garde les nouvelles lignes

Ces quatre "astuces" combinées dans un extrait sont très utiles pour afficher rapidement le code source d'une page Web, ligne après ligne, chaque ligne étant numérotée, tous les caractères spéciaux comme '\ t' ou les nouvelles lignes n'étant pas interprétés, et avec les nouvelles lignes. présent:

import urllib
from time import clock,sleep

sock = urllib.urlopen('http://docs.python.org/')
ch = sock.read()
sock.close()


te = clock()
for i,line in enumerate(ch.splitlines(1)):
    print str(i) + ' ' + repr(line)
t1 = clock() - te


print "\n\nIn 3 seconds, I will print the same content, using '\\n'.join(....)\n" 

sleep(3)

te = clock()
# here's the point of interest:
print '\n'.join(str(i) + ' ' + repr(line)
                for i,line in enumerate(ch.splitlines(1)) )
t2 = clock() - te

print '\n'
print 'first  display took',t1,'seconds'
print 'second display took',t2,'seconds'

Avec mon ordinateur pas très rapide, j'ai eu:

first  display took 4.94626048841 seconds
second display took 0.109297410704 seconds
2
eyquem
import tempfile
import cPickle

class DiskFifo:
    """A disk based FIFO which can be iterated, appended and extended in an interleaved way"""
    def __init__(self):
        self.fd = tempfile.TemporaryFile()
        self.wpos = 0
        self.rpos = 0
        self.pickler = cPickle.Pickler(self.fd)
        self.unpickler = cPickle.Unpickler(self.fd)
        self.size = 0

    def __len__(self):
        return self.size

    def extend(self, sequence):
        map(self.append, sequence)

    def append(self, x):
        self.fd.seek(self.wpos)
        self.pickler.clear_memo()
        self.pickler.dump(x)
        self.wpos = self.fd.tell()
        self.size = self.size + 1

    def next(self):
        try:
            self.fd.seek(self.rpos)
            x = self.unpickler.load()
            self.rpos = self.fd.tell()
            return x

        except EOFError:
            raise StopIteration

    def __iter__(self):
        self.rpos = 0
        return self
2
piotr

Emulation d'une instruction switch. Par exemple, switch (x) {..}:

def a():
  print "a"

def b():
  print "b"

def default():
   print "default"

apply({1:a, 2:b}.get(x, default))
2
GabiMe

En fait, je viens de créer cela, mais je pense que ce sera un outil de débogage très utile. 

def dirValues(instance, all=False):
    retVal = {}
    for prop in dir(instance):
        if not all and prop[1] == "_":
            continue
        retVal[prop] = getattr(instance, prop)
    return retVal

J'utilise habituellement dir () dans un contexte pdb, mais je pense que cela sera beaucoup plus utile:

(pdb) from pprint import pprint as pp
(pdb) from myUtils import dirValues
(pdb) pp(dirValues(someInstance))
1
Josh Russo

Une liste personnalisée qui, multipliée par une autre liste, retourne un produit cartésien ... La bonne chose est que le produit cartésien est indexable, pas comme celui de itertools.product (mais les multiplicandes doivent être des séquences, pas des itérateurs).

import operator

class mylist(list):
    def __getitem__(self, args):
        if type(args) is Tuple:
            return [list.__getitem__(self, i) for i in args]
        else:
            return list.__getitem__(self, args)
    def __mul__(self, args):
        seqattrs = ("__getitem__", "__iter__", "__len__")
        if all(hasattr(args, i) for i in seqattrs):
            return cartesian_product(self, args)
        else:
            return list.__mul__(self, args)
    def __imul__(self, args):
        return __mul__(self, args)
    def __rmul__(self, args):
        return __mul__(args, self)
    def __pow__(self, n):
        return cartesian_product(*((self,)*n))
    def __rpow__(self, n):
        return cartesian_product(*((self,)*n))

class cartesian_product:
    def __init__(self, *args):
        self.elements = args
    def __len__(self):
        return reduce(operator.mul, map(len, self.elements))
    def __getitem__(self, n):
        return [e[i] for e, i  in Zip(self.elements,self.get_indices(n))]
    def get_indices(self, n):
        sizes = map(len, self.elements)
        tmp = [0]*len(sizes)
        i = -1
        for w in reversed(sizes):
            tmp[i] = n % w
            n /= w
            i -= 1
        return tmp
    def __add__(self, arg):
        return mylist(map(None, self)+mylist(map(None, arg)))
    def __imul__(self, args):
        return mylist(self)*mylist(args)
    def __rmul__(self, args):
        return mylist(args)*mylist(self)
    def __mul__(self, args):
        if isinstance(args, cartesian_product):
            return cartesian_product(*(self.elements+args.elements))
        else:
            return cartesian_product(*(self.elements+(args,)))
    def __iter__(self):
        for i in xrange(len(self)):
            yield self[i]
    def __str__(self):
        return "[" + ",".join(str(i) for i in self) +"]"
    def __repr__(self):
        return "*".join(map(repr, self.elements))
1
fortran

Pour Python 2.4+ ou une version antérieure:

for x,y in someIterator:
  listDict.setdefault(x,[]).append(y)

En Python 2.5+, il existe une alternative utilisant defaultdict .

1
vartec

Parcourez tous les éléments itérables (liste, ensemble, fichier, flux, chaînes de caractères, peu importe), de N'IMPORTE QUELLE taille (y compris la taille inconnue), par morceaux de x éléments:

from itertools import chain, islice

def chunks(iterable, size, format=iter):
    it = iter(iterable)
    while True:
        yield format(chain((it.next(),), islice(it, size - 1)))

>>> l = ["a", "b", "c", "d", "e", "f", "g"]
>>> for chunk in chunks(l, 3, Tuple):
...         print chunk
...     
("a", "b", "c")
("d", "e", "f")
("g",)
1
e-satis

Lors du débogage, vous souhaitez parfois voir une chaîne avec un éditeur de base. Pour afficher une chaîne avec le bloc-notes:

import os, tempfile, subprocess

def get_Rand_filename(dir_=os.getcwd()):
    "Function returns a non-existent random filename."
    return tempfile.mkstemp('.tmp', '', dir_)[1]

def open_with_notepad(s):
    "Function gets a string and shows it on notepad"
    with open(get_Rand_filename(), 'w') as f:
        f.write(s)
        subprocess.Popen(['notepad', f.name])
0
iTayb