IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

modification dans une liste de liste pas effective


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de bringer
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2009
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2009
    Messages : 125
    Par défaut modification dans une liste de liste pas effective
    bonjour,

    je traite une liste de liste de tuple qui se transformera plus tard en liste de tuples. J'ai une fonction de traitement ci jointe qui doit me faire des modification au niveau le plus bas dans la liste.
    Les modification prisent à ce niveau fonctionnent bien, mais quand je renvoie ma liste de depart (de plus haut niveau), les modification ne sont pas effectives, comme si j'avais travaillé avec une copie de liste et non pas l'originale

    Quelqu'un a t-il une explication ?

    voici mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    global_list=[[('N1', 'P1', 0, 'PCS1'), ('N1', 'P1', 1, 'PCS2'), ('N1', 'P1', 0, 'PCS3')], [('N2', 'P2', 0, 'PCS1'), ('N2', 'P2', 0, 'PCS2')]]
    condition=(2,0, 3, '_')
    def condition_traitement(global_list, condition):
    	"""filtre les tuple des listes de facon à remplir les condition transmises
            Les conditions sont sous la forme d'un tuple de 4 elements
            elemt1 -> position dans le tuple de la condition à vérifier
            elemt2 -> condition à remplir
            elemt3 -> position du champs affecter par cette condition
            elemt4 -> conduite à tenir en cas ou la condition est remplie
            
            entree : global_list=liste de liste de tuple de la requete
                                    condition=tuple de traitement de la condition
            
            sortie : liste avec les condition vérifiées et triees
            """
     
    	#pour chaque liste de la liste
    	for member_list in global_list:
    	        #pour chaque tuple de la liste
    		for member_tuple in member_list:
    			#tranformer le tuple en liste pour pouvoir effectuer les modifs
    			member_tuple=list(member_tuple)
    			#si condition remplie
    			if member_tuple[condition[0]]==condition[1]:
    				#transformer l'element affecter par la condition
    				member_tuple[condition[2]]=condition[3]
    			#supprimer l'element test de condition
    			del member_tuple[condition[0]]
    			#tranformer la liste en tuple pour securite
    			member_tuple=tuple(member_tuple)
    	#retourner la liste modifiee
    	return global_list

  2. #2
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		for member_tuple in member_list:
    			#tranformer le tuple en liste pour pouvoir effectuer les modifs
    			member_tuple=list(member_tuple)
    list(member_tuple) ne transforme pas a proprement parler le tuple, en fait il n'y touche même pas, il te retourne simplement un nouvel objet liste avec les même éléments de member_tuple, ce qui fait que tes modifs s'effectue sur ce nouvel objet, et l'objet d'origine, reste à l'état d'origine. au lieur d'iteré directement sur les membres de member_list, tu pourrais itérer sur une liste d'indices de même longuer que member_list :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    global_list=[[('N1', 'P1', 0, 'PCS1'), ('N1', 'P1', 1, 'PCS2'), ('N1', 'P1', 0, 'PCS3')], [('N2', 'P2', 0, 'PCS1'), ('N2', 'P2', 0, 'PCS2')]]
    condition=(2,0, 3, '_')
    def condition_traitement(global_list, condition):
    	"""filtre les tuple des listes de facon à remplir les condition transmises
            Les conditions sont sous la forme d'un tuple de 4 elements
            elemt1 -> position dans le tuple de la condition à vérifier
            elemt2 -> condition à remplir
            elemt3 -> position du champs affecter par cette condition
            elemt4 -> conduite à tenir en cas ou la condition est remplie
            
            entree : global_list=liste de liste de tuple de la requete
                                    condition=tuple de traitement de la condition
            
            sortie : liste avec les condition vérifiées et triees
            """
     
    	#pour chaque liste de la liste
    	for member_list in global_list:
    	        #pour chaque tuple de la liste
    		for member_tuple_idx in xrange(len(member_list)):
    			#tranformer le tuple en liste pour pouvoir effectuer les modifs
    			member_tuple=list(member_list[member_tuple_idx])
    			#si condition remplie
    			if member_tuple[condition[0]]==condition[1]:
    				#transformer l'element affecter par la condition
    				member_tuple[condition[2]]=condition[3]
    			#supprimer l'element test de condition
    			del member_tuple[condition[0]]
    			#tranformer la liste en tuple pour securite
    			member_list[member_tuple_idx]=tuple(member_tuple)
    	#retourner la liste modifiee
    	return global_list

  3. #3
    Membre confirmé Avatar de bringer
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2009
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2009
    Messages : 125
    Par défaut
    merci de ton aide N.tox

    je viens d'essayer et cela fonctionne. Mais si je fais par exemple un essai comme ceci:

    a=[[1,2,3],[4,5,6]]
    a[0][1]=45
    j'obtient bien
    a=[[1,45,6],[4,5,6]]

    alors pouquoi, là , ca fonctionne ?

  4. #4
    Membre émérite
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    		for member_tuple_idx in member_list: #c'est comme si ici tu disais member_tuple= member_list[x]
    			member_tuple=list(member_list[member_tuple_idx])
    			#puis la tu donne un autre valeur à member_tuple, ce qui revient à dire :
    			#"Ok, bon ben en fait j'me suis trompé, member_tuple c'est plus un
    			#élément de member_list mais une liste qui le copie"
    si ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a=[[1,2,3],[4,5,6]]
    a[0][1]=45
    j'obtiens bien
    a=[[1,45,6],[4,5,6]]
    fonctionne, c'est par ce tu dit "Ok, l'élément à l'emplacement 1 de l'élément liste à l'emplacement 0 de a est égale à 45", ce qui remplace 2 par 45, parceque qu'ici on lui a dit que à cet endroit précis il devait mettre 45, maintenant regardes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> a=[[1,2,3],[4,5,6]]
    >>> b=a[0][1]
    >>> b=45
    >>> a
    [[1,2,3],[4,5,6]]
    >>> b
    45
    C'est exactement ce que tu faisait dans ta boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> a=b=0
    >>> a
    0
    >>> b
    0
    >>> b=5
    >>> b
    5
    >>> a
    0

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    N.tox a confirmé de façon anticipée ce que j’avais écrit, à savoir que je comprends les choses comme suit:



    Quand le programme fait for member_tuple in member_list,
    il crée un nouvel objet numéro 1 à partir d’une portion de l’objet member_list et il lui affecte l’étiquette "member_tuple".

    Puis, comme l’a dit N.tox, list(member_tuple) produit un nouvel objet numéro 2 à partir de l’objet nouveau numéro 1 et, l’instruction étant member_tuple= list(member_tuple) , le programme détache l’étiquette “member_tuple“ de l’objet nouveau numéro 1 pour l’affecter à l’objet nouveau numéro 2.

    Dès lors, l’objet nouveau numéro 1 n’existe plus aux yeux du programme, car s’il peut y avoir plusieurs étiquettes sur un objet (ce sont des alias), une étiquette ne peut pas désigner plusieurs objets. Quand le garbage collector va s’en occuper, la zone mémoire correspondant à l’ex-nouveau objet numéro 1 sera libérée.

    Il ne reste alors plus que le nouvel objet numéro 2 de type liste, et la liste initiale member_list qui n’a subi aucune modification et qui n’en subit aucune par la suite puisque ton code ne s’occupe ensuite que de member_tuple







    Dans le cas a=[[1,2,3],[4,5,6]] par contre,

    a[0][1] DÉSIGNE le second élément de la première sous-liste de a et l’instruction a[0][1]=45 ordonne que cet élément devienne 45: elle ne CRÉE PAS un nouvel objet, car a n’est pas un nouveau nom pour un objet dupliquant une portion d’un objet plus vaste, comme c’était le cas avec for member_tuple in member_list qui revient à
    for i in range(member_list):
    membre_tuple = member_list[i]


    C’est pourquoi N.tox te propose un code dans lequel l’instruction member_list[member_tuple_idx]=tuple(member_tuple)
    réalise la modification de la portion de member_list à modifier, alors que member_tuple=tuple(member_tuple) ne faisait qu’agir sur un objet indépendant de la liste.


    ---------------------------------

    Ceci dit, il y a des choses à améliorer.



    - L’une est que tout au long de l’exécution, le programme “s’amuse“ à répéter les mêmes tâches:
    dans if member_tuple[condition[0]]==condition[1]:, il lui faut trouver à chaque fois la valeur condition[0] et la valeur condition[1] dans l’objet condition.

    Tandis que si tu crées un alias: c0 = condition[0] , cet alias permet au programme d’aller chercher directement à l’endroit précis de la mémoire vive où elle se trouve la valeur condition[0], et non plus de l’obliger à repérer d’abord l’objet condition puis de s’orienter dedans afin de trouver le premier élément.

    Ceci se répète pour condition[1] et condition[2] et condition[3]. Il n’y paraît pas comme ça, mais l’usage d’alias améliore plus ou moins fortement la vitesse et ce sera d’autant plus notable que la liste à traiter est longue.



    - Je pense aussi que ces modifications répétées de type pour une séquence donnée sont assez lourdingues.

    Ici encore, l’usage d’un découpage de tuple en jouant avec les indices , bien que ça apparaisse assez bourin à vue d’œil, est fort efficace et rapide.

    Je proposer donc l’algorithme suivant sur ces principes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    from time import clock
     
    global_list=[[('N1', 'P1', 0, 'PCS1'), ('N1', 'P1', 1, 'PCS2'), ('N1', 'P1', 0, 'PCS3')],
                 [('N2', 'P2', 0, 'PCS1'), ('N2', 'P2', 0, 'PCS2')]]
     
    for u in global_list:
        print u
    print
     
    print '---------------------------'
     
     
    te = clock()
    c0,c1,c2,c3=(2, 0, 3, '_')
    def condition_traitement(global_list, igt):
        li_global = []
        for member_list in global_list:
            souli = []
            for tu in member_list:
                if tu[c0]==c1:
                    TU = tu[0:c2]+(c3,)+tu[c2+1:]
                else:
                    TU = tu
                souli.append( TU[0:c0] + TU[c0+1:] )
            li_global.append(souli)
        return li_global
     
     
    li = condition_traitement(global_list, igt)
    tf = clock()
     
    for el in li:
        print el
    print tf-te
    J’ai fait un test comparatif sommaire, avec clock(), de ce code avec le tien modifié pour qu’il donne le bon résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    global_list=[[('N1', 'P1', 0, 'PCS1'), ('N1', 'P1', 1, 'PCS2'), ('N1', 'P1', 0, 'PCS3')], [('N2', 'P2', 0, 'PCS1'), ('N2', 'P2', 0, 'PCS2')]]
     
     
    te = clock()
    condition=(2,0, 3, '_')
    def condition_traitement(global_list, condition):
    	"""filtre les tuple des listes de facon à remplir les condition transmises
            Les conditions sont sous la forme d'un tuple de 4 elements
            elemt1 -> position dans le tuple de la condition à vérifier
            elemt2 -> condition à remplir
            elemt3 -> position du champs affecter par cette condition
            elemt4 -> conduite à tenir en cas ou la condition est remplie
            
            entree : global_list=liste de liste de tuple de la requete
                                    condition=tuple de traitement de la condition
            
            sortie : liste avec les condition vérifiées et triees
            """
     
    	#pour chaque liste de la liste
    	for member_list in global_list:
    	        #pour chaque tuple de la liste
    		for i,member_tuple in enumerate(member_list):
    			#tranformer le tuple en liste pour pouvoir effectuer les modifs
    			member_tuple=list(member_tuple)
    			#si condition remplie
    			if member_tuple[condition[0]]==condition[1]:
    				#transformer l'element affecter par la condition
    				member_tuple[condition[2]]=condition[3]
    			#supprimer l'element test de condition
    			del member_tuple[condition[0]]
    			#tranformer la liste en tuple pour securite
    			member_list[i]=tuple(member_tuple)
    	#retourner la liste modifiee
    	return global_list
     
    li = condition_traitement(global_list, igt)
    tf = clock()
     
    for el in li:
        print el
    print tf-te

    Sur trois essais, j’ai trouve une moyenne de 0,00012413 seconde pour mon code et 0,00015783 seconde pour le tien, soit 21% de moins pour mon code.

  6. #6
    Membre confirmé Avatar de bringer
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2009
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2009
    Messages : 125
    Par défaut
    bonjour et merci à vous deux pour toutes ces explications et conseils avisés.

    Je pense avoir bien compris le mécanisme des affectations en mémoire maintenant.

    Encore merci
    Bringer

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Modification dans une bdd via une liste choisie via une checkbox
    Par LuffyWinchester dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 20/03/2015, 15h41
  2. Réponses: 0
    Dernier message: 15/12/2013, 16h35
  3. Réponses: 4
    Dernier message: 01/03/2010, 21h00
  4. Réponses: 2
    Dernier message: 17/02/2005, 00h00
  5. Sélection valeur par défaut dans une zone de liste
    Par Cécile154 dans le forum IHM
    Réponses: 2
    Dernier message: 15/02/2005, 18h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo