C'est une nouvelle sélection de trucs et astuces sur Python et la programmation de mon canal Telegram @pythonetc.
←
Publications précédentesLe symbole
\
dans la chaîne régulière a une signification spéciale.
\t
est un caractère de tabulation,
\r
est un retour chariot, etc.
Vous pouvez utiliser des chaînes brutes pour désactiver ce comportement.
r'\t'
est juste une barre oblique inverse et
t
.
Vous ne pouvez évidemment pas utiliser
'
inside
r'...'
. Cependant, il peut toujours être échappé par
\
, mais
\
est conservé dans la chaîne:
>>> print(r'It\'s insane!') It\'s insane!
Les compréhensions de liste peuvent contenir plusieurs clauses
for
et
if
:
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)]
De plus, toute expression dans
for
et
if
peut utiliser toutes les variables définies avant:
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) ]
Vous pouvez mélanger
if
s et
for
s comme vous le souhaitez:
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) ]
La fonction
sorted
vous permet de fournir une méthode personnalisée pour le tri. Cela se fait avec l'argument
key
, qui décrit comment convertir les valeurs d'origine en valeurs réellement comparées:
>>> 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'}]
Hélas, toutes les bibliothèques qui fonctionnent avec la comparaison ne prennent pas en charge cet argument
key
. Les exemples notables sont
heapq
(prise en charge partielle) et
bisect
(pas de prise en charge).
Il y a deux façons de gérer la situation. La première consiste à utiliser des objets personnalisés qui prennent en charge la comparaison appropriée:
>>> 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']
Cependant, vous devrez peut-être créer plusieurs versions de ces classes car il existe plusieurs façons de comparer les objets. Cela peut être fastidieux, mais peut être facilement résolu par la deuxième façon.
Au lieu de créer des objets personnalisés, vous pouvez utiliser des tuples
(a, b)
où
a
est la valeur à comparer (alias prioirty) et
b
est la valeur d'origine:
>>> 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']
La différence entre la définition de fonction et la définition de générateur est la présence du mot-clé
yield
dans le corps de la fonction:
In : def f(): ...: pass ...: In : def g(): ...: yield ...: In : type(f()) Out: NoneType In : type(g()) Out: generator
Cela signifie que pour créer un générateur vide, vous devez faire quelque chose comme ceci:
In : def g(): ...: if False: ...: yield ...: In : list(g()) Out: []
Cependant, étant
yield from
que le
yield from
supports d'itérateurs simples, cette version la plus belle serait la suivante:
def g(): yield from []
En Python, vous pouvez chaîner des opérateurs de comparaison:
>>> 0 < 1 < 2 True >>> 0 < 1 < 0 False
De telles chaînes ne doivent pas être mathématiquement valides, vous pouvez mélanger
>
et
<
:
>>> 0 < 1 > 2 False >>> 0 < 1 < 2 > 1 > 0 True
D'autres opérateurs tels que
==
,
is
et
in
sont également pris en charge:
>>> [] is not 3 in [1, 2, 3] True
Chaque opérateur est appliqué aux deux opérandes les plus proches.
a OP1 b OP2 c
est strictement égal à
(a OP1 b) AND (b OP2 c)
. Aucune comparaison entre
a
et
c
n'est implicite:
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)
Sortie:
1 < 2 2 <= 3 3 == 3 True