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

const

12 réponses
Avatar
JBB
Je cherche un moyen de faire l'équivalent d'un const en C/C++.
ceci afin d'éviter la modification de certains objets par d'autres.

ex:
class Maclass(object):
def __init__(self):
self.x = 1
def reset(self):
self.x = 0

def f(i):
i.reset()

x = Maclasse()
f(x)
#j'aimerais être sur que l'appel de f ne modifie pas x
et donc empêcher que f appelle reset()

Voici l'état de mes réflexions:
Je peux faire de Maclasse un type 'terminal' comme str ou tupple que l'on ne peut pas modifier, mais je trouve cette solution
contraignante.
Soit je passe a f un copie de x ( ce que je trouve contraignant aussi, en plus d'être peut performant), de plus ça n'empêchera
pas f de modifier ma copie (pour rien).
Soit avant d'appeler f je supprime la methode reset() de x et je la remet après (?)
Sinon, à la Java je pourrais passer a f seulement une interface sur x ( mais cela ne doit pas avoir de sens en Python)

Bref je cherche une solution à la fois propre et performante.

10 réponses

1 2
Avatar
hg
JBB wrote:

Je cherche un moyen de faire l'équivalent d'un const en C/C++.
ceci afin d'éviter la modification de certains objets par d'autres.

ex:
class Maclass(object):
def __init__(self):
self.x = 1
def reset(self):
self.x = 0

def f(i):
i.reset()

x = Maclasse()
f(x)
#j'aimerais être sur que l'appel de f ne modifie pas x
et donc empêcher que f appelle reset()

Voici l'état de mes réflexions:
Je peux faire de Maclasse un type 'terminal' comme str ou tupple que l'on
ne peut pas modifier, mais je trouve cette solution contraignante.
Soit je passe a f un copie de x ( ce que je trouve contraignant aussi, en
plus d'être peut performant), de plus ça n'empêchera pas f de modifier ma
copie (pour rien). Soit avant d'appeler f je supprime la methode reset()
de x et je la remet après (?) Sinon, à la Java je pourrais passer a f
seulement une interface sur x ( mais cela ne doit pas avoir de sens en
Python)

Bref je cherche une solution à la fois propre et performante.


Je me suis souvent posé cette question.

Une situation analogue qu'on voit souvent est que self._private ou
self.__private ne sont pas privées ... et que quand la question est posée,
la réponse des gourous est en général "...if a guy is stupid enough to
access a self._xxxx ... let him ! ...."

Ce qui nous rammène aux règles de codage.

Ma solution: mes "constantes" sont toutes en lettres capitales ... comme ça
je sais qu'il ne faut pas y toucher.


hg

Avatar
hg
Philippe Bouige wrote:

In article <x99Vh.79602$, hg wrote:
JBB wrote:

Je cherche un moyen de faire l'équivalent d'un const en C/C++.
ceci afin d'éviter la modification de certains objets par d'autres.



A voir sur le Web :

http://all4dev.libre-entreprise.org/index.php/Des_constantes_en_python
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207

Cordialement Philippe


Merci,

Je note une petite coquille
http://all4dev.libre-entreprise.org/index.php/Des_constantes_en_python
"if attr in Const._items: # En python 2.1, écrire if attr in
Const.__items.keys()"

Par contre pour moi l'intérêt est de partager les constantes d'un module à
l'autre ce qui ne semble pas fonctionner avec cette implémentation ... mais
je rate puet-être quelque chose:
"""
t1.py
"""
import consts
import t2
class toto:
def __init__(self):
l_c = consts.Const()

l_c.C1 = 'tata'
print l_c.C1
l_t = t2.titi()




l= toto()
"""
t2.py
"""
import consts


class titi:
def __init__(self):
l_c = consts.Const()
# print 'ICI ', l_c.C1
print l_c.C1



Avatar
pbouige
In article <x99Vh.79602$, hg wrote:
JBB wrote:

Je cherche un moyen de faire l'équivalent d'un const en C/C++.
ceci afin d'éviter la modification de certains objets par d'autres.



A voir sur le Web :

http://all4dev.libre-entreprise.org/index.php/Des_constantes_en_python
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207

Cordialement Philippe


Avatar
Bruno Desthuilliers
Je cherche un moyen de faire l'équivalent d'un const en C/C++.
ceci afin d'éviter la modification de certains objets par d'autres.

ex:
class Maclass(object):
def __init__(self):
self.x = 1
def reset(self):
self.x = 0

def f(i):
i.reset()

x = Maclasse()
f(x)
#j'aimerais être sur que l'appel de f ne modifie pas x
et donc empêcher que f appelle reset()


Pourquoi appeller cette méthode alors ?????



Voici l'état de mes réflexions:
Je peux faire de Maclasse un type 'terminal'


immutable.

comme str ou tupple que
l'on ne peut pas modifier, mais je trouve cette solution contraignante.

Soit je passe a f un copie de x ( ce que je trouve contraignant aussi,
en plus d'être peut performant), de plus ça n'empêchera pas f de
modifier ma copie (pour rien).
Soit avant d'appeler f je supprime la methode reset() de x et je la
remet après (?)


T'a pas l'impression de te compliquer un peu la vie ?

Sinon, à la Java je pourrais passer a f seulement une interface sur x (
mais cela ne doit pas avoir de sens en Python)


Non. Mais tu peux utiliser un proxy:

class RestrictiveProxy(object):
def __init__(self, obj, *dont_proxy):
self.__obj = obj
self.__dont_proxy = dont_proxy

def __check(self, name):
if name in self.__dont_proxy:
raise AttributeError("access to %s is restricted")

def __getattr__(self, name):
self.__check(name)
return getattr(self.__obj, name)

# je zappe le __setattr__ parce qu'il est
# un peu plus compliqué et que ce n'est pas
# nécécessaire pour l'exemple


x = MaClasse()
try:
f(RestrictiveProxy(x, 'reset'))
except AttributeError, e:
print "semble ok ? %s" %e
else:
print "marche pas..."

(NB : pas testé)

Bref je cherche une solution à la fois propre et performante.


La solution "propre et performante" est de ne pas appeler x.reset, ou de
ne pas passer x à f.

Avatar
tool69
Bonsoir,

J'essaye depuis quelques temps de parser des strucutures du genre :

"du texte ici ${1:truc} du texte là ${2:machin}"

En sortie, il me faudrait :

- l'index du début de chaque tag
- le numero du tag correspondant
- le contenu du tag (qui se trouve derrière le délimiteur ':')

Pour le premier tag, cela donnerait donc [13,1,'truc'].

J'ai bien réussi à faire ça avec des regexps, le problème arrive
évidemment lorsque je veux parser des strucutres imbriquées comme celle-ci :

"du texte ici ${1:truc} du texte là ${2:${3:truc} ${4:truc}}"

Dans ce cas, il me faudra pour chaque tag rencontré les 3 points
précédemment cités, ainsi qu'un quatrième : le niveau d'imbrication.

A part écrire des choses à la main (ce que j'ai fait) avec des
string.find ou string.index, qu'auriez-vous à me proposer ? idées,
modules (j'ai déjà essayé PyParsing, et l'auteur est très sympas
d'ailleurs, mais ça ne convient pas).

D'avance merci,

Kib².
Avatar
Mihamina (R12y) Rakotomandimby
tool69 - <46267e5b$0$29404$ :

Bonsoir,


Bonsoir,

J'essaye depuis quelques temps de parser des strucutures du genre :
[...]

"du texte ici ${1:truc} du texte là ${2:${3:truc} ${4:truc}}"


- Je vois mal le rapport avec les "const". Mais bon tu as dû te tromper de
bouton (Follow-up au lieu de New)

- Est-ce que tu dois vraiment le faire en Python?

Avatar
Mihamina (R12y) Rakotomandimby
tool69 - <46267e5b$0$29404$ :

Bonsoir,


Bonsoir,

J'essaye depuis quelques temps de parser des strucutures du genre :
[...]

"du texte ici ${1:truc} du texte là ${2:${3:truc} ${4:truc}}"


- Je vois mal le rapport avec les "const". Mais bon tu as dû te tromper de
bouton (Follow-up au lieu de New)
- Est-ce que tu dois vraiment le faire en Python?
- Si tu arrive à le faire pour "un niveau d'imbrication" en utilisant la
recursivité, tu devrais pouvoir le faire sur "plusieurs niveaux". Mais il y
a des langages très bien adaptés pour utiliser la recursivité, d'ou ma
question précédente.
- Tu aurais pu donner un exemple de ce que tu as trouvé et qui marche
partiellement.

Avatar
tool69
Désolé pour le bouton, depuis que je suis passé à cet écran Wide, j'ai
un peu de mal avec les caractères tout petits.

Bon, sinon voilà un des scripts que j'ai écris :

---------------------
#!/usr/bin/env python
# -*- coding: latin1 -*-

import string

STARTER = "${"
ENDER = "}"

def parse(template):
state = 0
opened_brack = 0
static = ""
fields = []
starts = []
j=0
print 'Examining n', template,'n'
for c in template :
i=j
#print 'examine',c,'starts',starts,i
if c == '$' :
state = 1
elif c == '{' and state == 1 :
opened_brack += 1
starts.append(i-1)
elif c == '}' :
st = starts.pop()
fields.append( [st, template[st+len(STARTER):i] ,
opened_brack-1])
opened_brack -= 1
state = 0
else :
if state == 0 :
static += c
j += 1
print 'Static Textnt',static,'n'
return fields

tpl = "Un ${1:truc} avec son ${2:${3:bidule} dans un
${4:${5:${6:machin}}}}."

for el in parse(tpl) : print el
---------------------

Ca marche, mais bon, je trouve ça un peu 'bidouille'
Avatar
Mihamina (R12y) Rakotomandimby
tool69 - <46268b50$0$13276$ :

Bon, sinon voilà un des scripts que j'ai écris :


Je voulais te le nettoyer un peu, mais apres bientot 3 mois de cure de PHP
sans rien avoir écrit en Python, je me retrouve incapable d'écrire un bout
de code décent (et pourtant je suis assez peu rigoureux).
Bon ben faut que je m'invente des petits trucs à faire en Python...

Avatar
Bruno Desthuilliers
Désolé pour le bouton, depuis que je suis passé à cet écran Wide, j'ai
un peu de mal avec les caractères tout petits.

Bon, sinon voilà un des scripts que j'ai écris :

---------------------
#!/usr/bin/env python
# -*- coding: latin1 -*-

import string

STARTER = "${"
ENDER = "}"

def parse(template):
state = 0
opened_brack = 0
static = ""
fields = []
starts = []
j=0
print 'Examining n', template,'n'
for c in template :
i=j
#print 'examine',c,'starts',starts,i
if c == '$' :
state = 1
elif c == '{' and state == 1 :
opened_brack += 1
starts.append(i-1)
elif c == '}' :
st = starts.pop()
fields.append( [st, template[st+len(STARTER):i] ,
opened_brack-1])
opened_brack -= 1
state = 0
else :
if state == 0 :
static += c
j += 1
print 'Static Textnt',static,'n'
return fields

tpl = "Un ${1:truc} avec son ${2:${3:bidule} dans un
${4:${5:${6:machin}}}}."

for el in parse(tpl) : print el
---------------------

Ca marche,


Tel que, ça ne correspond pas à ton cahier des charges.

mais bon, je trouve ça un peu 'bidouille'


Le fait de faire le parsing à la mano, dans un cas aussi simple, n'est
pas nécessairement de la bidouille en soi. Par contre, ton code est AMHA
inutilement compliqué.

START = "${"
END = "}"

_start_len = len(START)
_end_len = len(END)

def parse(template):
fields = []
fields_starts = []

for position, _ in enumerate(template):
if template[position:position + _start_len] == START:
fields_starts.append(position)
elif template[position:position + _end_len] == END:
depth = len(fields_starts)
if depth:
start = fields_starts.pop()
key, content =
template[start + _start_len:position].split(':', 1)
fields.append((start, int(key), content, depth-1))
return fields

tpl = """
Un ${1:truc} avec son ${2:${3:bidule} dans un ${4:${5:${6:machin}}}}.
"""
for field in parse(tpl):
print field

(3, 1, 'truc', 0)
(26, 3, 'bidule', 1)
(54, 6, 'machin', 3)
(50, 5, '${6:machin}', 2)
(46, 4, '${5:${6:machin}}', 1)
(22, 2, '${3:bidule} dans un ${4:${5:${6:machin}}}', 0)

HTH

1 2