Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Code Python2.x vers Python3.x

13 réponses
Avatar
Nicolas
Bonjour,

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?

Nicolas

10 réponses

1 2
Avatar
Pierre Maurette
Nicolas :
Bonjour,

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la comparaison
retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



Je n'ai pas encore pratiqué Python3.x. Vous devriez pouvoir conserver
une écriture en une ligne avec:
(type(a) is type(b)) and (a < b) #parenthèses surnuméraires volontaires

A adapter à la logique souhaitée en utilisant:

- les règles d'évaluation paresseuse des expressions logiques:
A and B, B n'est pas évaluée si A vaut False
A or B, B n'est pas évaluée si A vaut True

- De Morgan: !(A and B) = (!A or !B) et équivalents.

Enfin, c'est ce que je ferais pour aller vite, mais il se trouve que je
/lis/ facilement ce type d'expression, alors que certains trouvent ça
illisible. Attention toutefois, type(a) is type(b) renvoie False pour
deux types numériques comparables mais différents (2 et 2.6 par
exemple), ça se corrige également, mais ça commence à alourdir.
Peut-être y a-t-il beaucoup plus simple ?

--
Pierre Maurette
Avatar
Alain Ketterlin
Nicolas writes:

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



En utilisant type() ?

-- Alain.
Avatar
Nicolas
Le 10/10/2011 15:10, Alain Ketterlin a écrit :
Nicolas writes:

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



En utilisant type() ?

-- Alain.


Je n'avais pas pensé à valider les arguments avant le test.
Merci Pierre et Alain.

Nicolas
Avatar
Nicolas
Le 10/10/2011 16:53, Nicolas a écrit :
Le 10/10/2011 15:10, Alain Ketterlin a écrit :
Nicolas writes:

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



En utilisant type() ?

-- Alain.


Je n'avais pas pensé à valider les arguments avant le test.
Merci Pierre et Alain.

Nicolas


Après quelques essais, je vais garder la forme développée avec un
try/except. La validation des arguments est trop restrictive.
Par exemple, la comparaison d'un entier et d'un flottant est autorisée.
Alors que type(int) et type(float) sont différents.

Nicolas
Avatar
Laurent Pointal
Nicolas wrote:

Le 10/10/2011 16:53, Nicolas a écrit :
Le 10/10/2011 15:10, Alain Ketterlin a écrit :
Nicolas writes:

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



En utilisant type() ?

-- Alain.


Je n'avais pas pensé à valider les arguments avant le test.
Merci Pierre et Alain.

Nicolas


Après quelques essais, je vais garder la forme développée avec un
try/except. La validation des arguments est trop restrictive.
Par exemple, la comparaison d'un entier et d'un flottant est autorisée.
Alors que type(int) et type(float) sont différents.



Tu peux aussi utiliser un test isinstance()
http://docs.python.org/release/3.1.3/library/functions.html#isinstance
En spécifiant un tuple de plusieurs classes comme classinfo.
Avatar
Nicolas
Le 13/10/2011 18:24, Laurent Pointal a écrit :
Nicolas wrote:

Le 10/10/2011 16:53, Nicolas a écrit :
Le 10/10/2011 15:10, Alain Ketterlin a écrit :
Nicolas writes:

Soit, le code suivant :
self.records = [r for r in self.records if r[self.key]<other]

Avec Python2.x, si self.key et other sont de type différents, la
comparaison retourne True ou False en fonction des types.
Avec Python3.x, ce n'est pas permis. Une exception est retournée.

Mon code modifié pour Python 3.x est :
rec = []
for r in self.records :
try :
if r[self.key]<other :
rec.append(r)
except TypeError :
pass
self.records = rec

Y a t-il une écriture plus concise possible ?



En utilisant type() ?

-- Alain.


Je n'avais pas pensé à valider les arguments avant le test.
Merci Pierre et Alain.

Nicolas


Après quelques essais, je vais garder la forme développée avec un
try/except. La validation des arguments est trop restrictive.
Par exemple, la comparaison d'un entier et d'un flottant est autorisée.
Alors que type(int) et type(float) sont différents.



Tu peux aussi utiliser un test isinstance()
http://docs.python.org/release/3.1.3/library/functions.html#isinstance
En spécifiant un tuple de plusieurs classes comme classinfo.



L'exemple avec "int" et "None" est un cas particulier qui permet de
comprendre le problème facilement.

Dans le cas qui m'intéresse, "r[self.key]" est un champ d'une base de
données et "other" est une valeur passée par l'utilisateur. Le code est
générique pour tous les champs de la base de données qui ont des types
différents et qui peuvent ne pas être renseignés (None).

L'utilisation de "isinstance()" est possible mais rendrait le code
inutilement compliqué.

Nicolas
Avatar
Alain Ketterlin
Nicolas writes:

self.records = [r for r in self.records if r[self.key]<other]



En utilisant type() ?







Tu peux aussi utiliser un test isinstance()



Dans le cas qui m'intéresse, "r[self.key]" est un champ d'une base de
données



Donc il a un type, et ce type est connu.

et "other" est une valeur passée par l'utilisateur.



Donc c'est une chaîne de caractères.

Le code est générique pour tous les champs de la base de donn ées qui
ont des types différents et qui peuvent ne pas être renseignà ©s (None).



Générique ne veut pas dire que le type du champ est inconnu. A ta place
ce que je ferais est d'associer à chaque (type de) champ un comparateu r,
qui s'occupe de comparer à la valeur en provenance de l'utilisateur.

comp = comparateurs[self.key]
self.records = [r for r in self.records if comp(r[self.key],other)]

Ou, pour être un peu plus efficace, d'associer à chaque champ une
fonction qui transforme l'entrée de l'utilisateur en quelque chose de
comparable avec une valeur du champ en question. Ton code deviendrait :

ou encore

conv = convertisseurs[self.key](other)
self.records = [r for r in self.records if r[self.key] < conv]
if conv is not None else []

ou une combinaison des deux.

-- Alain.
Avatar
jmfauth
On 14 oct, 09:00, Nicolas wrote:

L'utilisation de "isinstance()" est possible mais rendrait le code
inutilement compliqué.





Pourquoi? C'est fait pour cela. Il me semble que la première
chose à faire avant de comparer est de trier ce qui est comparable.
Peu importe le type de donnée.

z = ['a', 1.0, 3, {}, set(), 99, None]
a = [e for e in z if isinstance(e, (int, float))]
a






[1.0, 3, 99]
other = 5
[e for e in a if e < other]






[1.0, 3]

jmf
Avatar
Nicolas
Le 14/10/2011 09:33, Alain Ketterlin a écrit :
Nicolas writes:

self.records = [r for r in self.records if r[self.key]<other]













En utilisant type() ?











Tu peux aussi utiliser un test isinstance()





Dans le cas qui m'intéresse, "r[self.key]" est un champ d'une base de
données



Donc il a un type, et ce type est connu.

et "other" est une valeur passée par l'utilisateur.



Donc c'est une chaîne de caractères.


Non.
Ici, utilisateur = programmeur (utilisateur de la base de données).

Le code est générique pour tous les champs de la base de données qui
ont des types différents et qui peuvent ne pas être renseignés (None).



Générique ne veut pas dire que le type du champ est inconnu. A ta place
ce que je ferais est d'associer à chaque (type de) champ un comparateur,
qui s'occupe de comparer à la valeur en provenance de l'utilisateur.

comp = comparateurs[self.key]
self.records = [r for r in self.records if comp(r[self.key],other)]

Ou, pour être un peu plus efficace, d'associer à chaque champ une
fonction qui transforme l'entrée de l'utilisateur en quelque chose de
comparable avec une valeur du champ en question. Ton code deviendrait :

ou encore

conv = convertisseurs[self.key](other)
self.records = [r for r in self.records if r[self.key]< conv]
if conv is not None else []

ou une combinaison des deux.




Ce que je veux, c'est que le code traduit en Python3 fonctionne
exactement comme le code d'origine écrit en Python2. Pour question de
compatibilité.

Nicolas

-- Alain.
Avatar
Nicolas
Le 14/10/2011 11:29, jmfauth a écrit :
On 14 oct, 09:00, Nicolas wrote:

L'utilisation de "isinstance()" est possible mais rendrait le code
inutilement compliqué.





Pourquoi? C'est fait pour cela. Il me semble que la première
chose à faire avant de comparer est de trier ce qui est comparable.
Peu importe le type de donnée.

z = ['a', 1.0, 3, {}, set(), 99, None]
a = [e for e in z if isinstance(e, (int, float))]
a






[1.0, 3, 99]
other = 5
[e for e in a if e< other]






[1.0, 3]

jmf


Comme je l'ai dit à Alain :
Ce que je veux, c'est que le code traduit en Python3 fonctionne
exactement comme le code d'origine écrit en Python2. Pour question de
compatibilité.

Nicolas
1 2