@Pythonetc compilation mars 2019


Ceci est la dixième collection de conseils et de programmation Python de mon flux @pythonetc.

Sélections précédentes .

0_0


0_0 est une expression complètement correcte en Python.

Trier la liste avec Aucun


Le tri d'une liste avec des valeurs None peut être une tâche ardue:

 In [1]: data = [  ...: dict(a=1),  ...: None,  ...: dict(a=-3),  ...: dict(a=2),  ...: None,  ...: ] In [2]: sorted(data, key=lambda x: x['a']) ... TypeError: 'NoneType' object is not subscriptable 

Vous pouvez essayer de supprimer tous les None et de les renvoyer après le tri (au début ou à la fin de la liste, selon la tâche):

 In [3]: sorted(  ...: (d for d in data if d is not None),  ...: key=lambda x: x['a']  ...: ) + [  ...: d for d in data if d is None  ...: ] Out[3]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 

Mais c'est gênant. Mieux vaut utiliser une key plus complexe:

 In [4]: sorted(data, key=lambda x: float('inf') if x is None else x['a']) Out[4]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 

Si nous parlons de types pour lesquels l'infini est inacceptable, vous pouvez trier les tuples:

 In [5]: sorted(data, key=lambda x: (1, None) if x is None else (0, x['a'])) Out[5]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 

Appelez random.seed ()


Lorsque vous bifurquez le processus, la graine aléatoire que vous utilisez sera copiée dans tous les processus résultants. En conséquence, le même résultat «aléatoire» peut être généré en eux.

Pour éviter cela, vous devez appeler manuellement random.seed() dans chaque processus. Mais si vous utilisez le module multiprocessing , il le fera pour vous.

Par exemple:

 import multiprocessing        import random                 import os                     import sys                    def test(a):                  print(random.choice(a), end=' ') a = [1, 2, 3, 4, 5]           for _ in range(5):            test(a)                   print()                       for _ in range(5):            p = multiprocessing.Process(   target=test, args=(a,) )                         p.start()                 p.join()                  print()                       for _ in range(5):            pid = os.fork()           if pid == 0:              test(a)               sys.exit()            else:                     os.wait()             print() 

Obtenez quelque chose comme ça:

 4 4 4 5 5 1 4 1 3 3 2 2 2 2 2 

De plus, si vous utilisez Python 3.7 et supérieur, grâce au nouveau at_fork at_fork, vous pouvez faire de même avec os.fork .

Le code Python 3.7 ci-dessus donne ce résultat:

 1 2 2 1 5 4 4 4 5 5 2 4 1 3 1 

Ajout à 0


À première vue, il semble que la sum([a, b, c]) équivalente à a + b + c , bien qu'en fait l'équivalent soit 0 + a + b + c . Cette expression ne peut donc pas fonctionner avec des types qui ne prennent pas en charge l'ajout à 0 :

 class MyInt: def __init__(self, value): self.value = value def __add__(self, other): return type(self)(self.value + other.value) def __radd__(self, other): return self + other def __repr__(self): class_name = type(self).__name__ return f'{class_name}({self.value})' In : sum([MyInt(1), MyInt(2)]) ... AttributeError: 'int' object has no attribute 'value' 

Pour résoudre ce problème, vous pouvez fournir un élément de départ personnalisé qui sera utilisé au lieu de 0 :

 In : sum([MyInt(1), MyInt(2)], MyInt(0)) Out: MyInt(3) 

sum conçu pour ajouter des types float et int , bien qu'il puisse fonctionner avec n'importe quel autre type personnalisé. Cependant, il refuse d'ajouter des bytes , bytearray et str , car join à cet effet:

 In : sum(['a', 'b'], '') ... TypeError: sum() can't sum strings [use ''.join(seq) instead] In : ints = [x for x in range(10_000)] In : my_ints = [Int(x) for x in ints] In : %timeit sum(ints) 68.3 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) In : %timeit sum(my_ints, Int(0)) 5.81 ms ± 20.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 



Achèvement de l'index dans Jupyter Notebook


À l'aide de la méthode _ipython_key_completions_ , _ipython_key_completions_ pouvez personnaliser l'achèvement de l'index dans un bloc-notes Jupyter. De cette façon, vous pouvez contrôler ce qui est affiché à l'écran si vous appuyez sur Tab après quelque chose comme d["x :



Notez que la méthode ne reçoit pas la chaîne à rechercher comme argument.

Source: https://habr.com/ru/post/fr447210/


All Articles