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

Substitution de chaîne de caractères

4 réponses
Avatar
none
Je souhaite utiliser python pour chaîner des programmes,
Les fichiers d'entrées de ces programmes contiennent beaucoup
d'informations sous forme de vecteurs.

J'ai donc besoin de modifier des colonnes en les remplaçant par les
valeurs contenues dans des listes, sans toucher aux valeurs adjacentes.
Comme je dois lancer beaucoup de calcul, il semble intéressant de faire
des modèles de fichier.

J'aimerais savoir s'il y a un moyen d'indicer des noms de variables lors
des substitutions de chaînes de caractères.

Cela permettrai de faire quelque chose du style :

[code]

modele = """
[..]

*** SECTION X01
X Y PRO STET
------------------------------------------------
%(X[0])g %(Y[0])g 39.5 0
%(X[1])g %(Y[1])g 48.5 59
%(X[2])g %(Y[2])g 55.5 116
%(X[3])g %(Y[3])g 60.5 171
%(X[4])g %(Y[4])g 63.5 224
%(X[5])g %(Y[5])g 64.5 275
%(X[6])g %(Y[6])g 63.5 324
%(X[7])g %(Y[7])g 60.5 371
%(X[8])g %(Y[8])g 55.5 416
%(X[9])g %(Y[9])g 48.5 459

[...]
"""
X = calcX()
Y = calcY()

file(file2,'w').write( modele % dict(X=X,Y=Y) )

[/code]

#-----------------------------------------------
# Resultat souhaité :

*** SECTION X01
X Y PRO STET
------------------------------------------------
0 1.02179 39.5 0
0.156434 1.12984 48.5 59
0.309017 1.09731 55.5 116
0.45399 1.02987 60.5 171
0.587785 1.00948 63.5 224
0.707107 0.910325 64.5 275
0.809017 0.925098 63.5 324
0.891007 0.843927 60.5 371
0.951057 0.824092 55.5 416
0.987688 0.757321 48.5 459


Si ce n'est pas possible facilement, quelle serait la façon pythonesque
de faire ?

--
Elby

4 réponses

Avatar
Christophe
Bonjour,

L'opérateur % peut prendre n'importe quel objet comme second argument,
il suffit qu'il ait une méthode __getitem__ (donc qu'il se comporte
comme un dictionnaire).

Par exemple, la classe suivante permet de construire un objet dont la
méthode __getitem__ évalue des expressions python :

class Eval:
def __init__(self, level=0):
frame = sys._getframe(1+level)
self.globals = frame.f_globals
self.locals = frame.f_locals
def __getitem__(self, item):
return eval(item%self, self.globals, self.locals)

Maintenant, il ne reste plus qu'à essayer ça :

print modele%Eval()


Christophe.
Avatar
Pierre Quentel
J'aimerais savoir s'il y a un moyen d'indicer des noms de variables lors
des substitutions de chaînes de caractères.

Je ne pense pas. Les substitutions sont de la forme format % valeur où

valeur est, soit une variable unique, soit un tuple, soit un
dictionnaire. Si c'est une variable ou un tuple on les prend les uns
après les autres pour boucher les trous ; si c'est un dictionnaire les
"trous" sont du genre %(nom)s et on cherche dans le dictionnaire la
valeur qui correspond à la clé "nom". On ne peut pas avoir %(X[i]) comme
tu le suggères (pas bête, d'ailleurs !)

Si ce n'est pas possible facilement, quelle serait la façon pythonesque
de faire ?

Tu peux faire comme ça :


#-----------------------
modele = """

*** SECTION X01
X Y PRO STET
------------------------------------------------
%1.5f %1.5f 39.5 0
%1.5f %1.5f 48.5 59
%1.5f %1.5f 55.5 116
%1.5f %1.5f 60.5 171
%1.5f %1.5f 63.5 224
%1.5f %1.5f 64.5 275
%1.5f %1.5f 63.5 324
%1.5f %1.5f 60.5 371
%1.5f %1.5f 55.5 416
%1.5f %1.5f 48.5 459

"""

# génération des données au hasard, pour l'exemple
import random
X = [ random.uniform(0,2) for i in range(10) ]
Y = [ random.uniform(0,2) for i in range(10) ]

# construction d'une liste avec les éléments dans l'ordre
# où ils apparaissent dans le modèle

arg = []
for i in range(len(X)):
arg+=[X[i],Y[i]]

print modele %tuple(arg)
#---------------------------

Le %1.5f signifie de formatter un réel (float) avec un chiffre avant et
5 chiffres après la virgule (le point, en fait)

A+
Pierre

Avatar
none
Bonjour,

L'opérateur % peut prendre n'importe quel objet comme second argument,
il suffit qu'il ait une méthode __getitem__ (donc qu'il se comporte
comme un dictionnaire).

Par exemple, la classe suivante permet de construire un objet dont la
méthode __getitem__ évalue des expressions python :

class Eval:
def __init__(self, level=0):
frame = sys._getframe(1+level)
self.globals = frame.f_globals
self.locals = frame.f_locals
def __getitem__(self, item):
return eval(item%self, self.globals, self.locals)

Maintenant, il ne reste plus qu'à essayer ça :

print modele%Eval()


Christophe.



C'est exactement ce que je cherchais !
Excellent !

Et dire que j'étais prêt à refaire l'opérateur % avec des expressions
rationnelles...

Merci

--
Elby

Avatar
Cémoi
Bonjour,

L'opérateur % peut prendre n'importe quel objet comme second argument,
il suffit qu'il ait une méthode __getitem__ (donc qu'il se comporte
comme un dictionnaire).


Je ne suis pas sur d'avoir bien compris.
Te referes tu a ce qui est expliqué dans le tutoriel de Python 2.4 au
chapitre 7.1, dans ce qu'ils appelent le '%(name)format' et qui consiste
a affecter une variable à son format via la clé correspondante du
dictionnaire passé comme parametre à l'opérateur %?
Dans ce cas la, pour en revenir au modele proposé par 'none', pour
acceder par exemple à X[2] il lui faut prealablement formater sa liste
pour la transformer en dictionnaire contenant la cle 'X[2]'.

Ma déduction est elle correcte ?

Dans l'affirmative et pour en revenir au modele proposé, la generation
d'un tel dictionnaire ne risque t'elle pas de consommer une quantité
considerable de mémoire si les listes sont de grande taille, sachant
qu'il faut une clé par element de chaque liste ?

Y a t'il pour l'opérateur % une autre syntaxe permettant d'acceder a un
element d'une liste, elle-meme etant une valeur d'un dictionnaire (dans
le cas du modele de 'none', 'X' serait la clé et la liste X serait sa
valeur) ?

Merci pour vos réponses.

Laurent


Par exemple, la classe suivante permet de construire un objet dont la
méthode __getitem__ évalue des expressions python :

class Eval:
def __init__(self, level=0):
frame = sys._getframe(1+level)
self.globals = frame.f_globals
self.locals = frame.f_locals
def __getitem__(self, item):
return eval(item%self, self.globals, self.locals)

Maintenant, il ne reste plus qu'à essayer ça :

print modele%Eval()


Christophe.