⬆️ ⬇️

Compilation @pythonetc, June 2019



This is the eleventh collection of Python tips and programming from my author's @pythonetc channel.



← Previous collections





The \ character in the normal string has a special meaning. \t is a tab character, \r is a line break, and so on.

')

To disable this behavior, you can use raw strings. Then r'\t' turns into just backslash and t .



Obviously, you cannot use ' inside r'...' . And although this restriction can be circumvented with \ , however, the \ line still remains:



 >>> print(r'It\'s insane!') It\'s insane! 




List generators can contain more than one pair of for and if expressions:



 In : [(x, y) for x in range(3) for y in range(3)] Out: [ (0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2) ] In : [ (x, y) for x in range(3) for y in range(3) if x != 0 if y != 0 ] Out: [(1, 1), (1, 2), (2, 1), (2, 2)] 


In addition, any expression inside for and if can use all previously defined variables:



 In : [ (x, y) for x in range(3) for y in range(x + 2) if x != y ] Out: [ (0, 1), (1, 0), (1, 2), (2, 0), (2, 1), (2, 3) ] 


You can mix if and for at your discretion:



 In : [ (x, y) for x in range(5) if x % 2 for y in range(x + 2) if x != y ] Out: [ (1, 0), (1, 2), (3, 0), (3, 1), (3, 2), (3, 4) ] 




The sorted function allows sorted to specify custom sorting methods. This is done using the key argument, which describes how to convert the original values ​​for later comparison:



 >>> x = [dict(name='Vadim', age=29), dict(name='Alex', age=4)] >>> sorted(x, key=lambda v: v['age']) [{'age': 4, 'name': 'Alex'}, {'age': 29, 'name': 'Vadim'}] 


Alas, not all libraries that work with comparison support the key argument. Of those that are heard, we can mention heapq (partial support) and bisect (no support).



In this situation, you can go two ways. You can use custom objects that support proper comparison:



 >>> class User: ... def __init__(self, name, age): ... self.name = name ... self.age = age ... def __lt__(self, other): ... return self.age < other.age ... >>> x = [User('Vadim', 29), User('Alex', 4)] >>> [x.name for x in sorted(x)] ['Alex', 'Vadim'] 


However, you may need to create several versions of these classes, because you can compare objects in different ways. This can be inconvenient, so there is a second way.



Instead of creating custom objects, you can use tuples (a, b) , in which a is the value to compare (priority) and b is the original value:



 >>> users = [dict(name='Vadim', age=29), dict(name='Alex', age=4)] >>> to_sort = [(u['age'], u) for u in users] >>> [x[1]['name'] for x in sorted(to_sort)] ['Alex', 'Vadim'] 




The difference between the definition and the function generator is the presence of the keyword yield in the function body:



 In : def f(): ...: pass ...: In : def g(): ...: yield ...: In : type(f()) Out: NoneType In : type(g()) Out: generator 


This means that to create an empty generator you need to do this:



 In : def g(): ...: if False: ...: yield ...: In : list(g()) Out: [] 


But since yield from supports simple iterators, a more pleasant version is:



 def g(): yield from [] 




In Python, you can create chains of comparison operators:



 >>> 0 < 1 < 2 True >>> 0 < 1 < 0 False 


Such chains do not have to be mathematically correct, you can mix > and < :



 >>> 0 < 1 > 2 False >>> 0 < 1 < 2 > 1 > 0 True 


== operators are also supported. is and in :



 >>> [] is not 3 in [1, 2, 3] True 


Each operator is applied to two adjacent operands. a OP1 b OP2 c strictly equivalent to (a OP1 b) AND (b OP2 c) . Comparing a and c not performed:



 class Spy: def __init__(self, x): self.x = x def __eq__(self, other): print(f'{self.x} == {other.x}') return self.x == other.x def __ne__(self, other): print(f'{self.x} != {other.x}') return self.x != other.x def __lt__(self, other): print(f'{self.x} < {other.x}') return self.x < other.x def __le__(self, other): print(f'{self.x} <= {other.x}') return self.x <= other.x def __gt__(self, other): print(f'{self.x} > {other.x}') return self.x > other.x def __ge__(self, other): print(f'{self.x} >= {other.x}') return self.x >= other.x s1 = Spy(1) s2 = Spy(2) s3 = Spy(3) print(s1 is s1 < s2 <= s3 == s3) 


Result:



 1 < 2 2 <= 3 3 == 3 True 

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



All Articles