📜 ⬆️ ⬇️

Selection @pythonetc, March 2019


This is the tenth collection of tips on Python and programming from my author’s @pythonetc channel.

Previous selections .

0_0


0_0 is a fully valid Python expression.

Sort the list with None


Sorting a list with None values ​​can be a daunting task:
')
 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 

You can try to delete all None and return them after sorting (to the beginning or to the end of the list, depending on the task):

 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] 

But it is inconvenient. It is better to use a more complex key :

 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] 

If we are talking about types for which infinity is unacceptable, you can sort 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] 

Call random.seed ()


When you fork a process, the random seed you use will be copied to all the resulting processes. As a result, they can generate the same "random" result.

To avoid this, you need to manually call random.seed() in each process. But if you use the multiprocessing module, it will do it for you.

For example:

 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() 

Get something like this:

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

Moreover, if you are using Python 3.7 or higher, thanks to the new at_fork at_fork you can do the same with os.fork .

The above Python 3.7 code gives the following result:

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

Addition with 0


At first glance, it seems that sum([a, b, c]) equivalent to a + b + c , although in fact the equivalent would be 0 + a + b + c . So this expression cannot work with types that do not support addition with 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' 

To fix this, you can provide a custom starting element that will be used instead of 0 :

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

sum intended for adding float and int types, although it can work with any other custom types. However, he refuses to add bytes , bytearray and str , since join for this purpose:

 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) 



Completing indexes in Jupyter Notebook


Using the _ipython_key_completions_ method, _ipython_key_completions_ can customize the completion of indexes in Jupyter Notebook. This way you can control what is displayed on the screen if you press Tab after something like d["x :



Note that the method does not get the search string as an argument.

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


All Articles