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 :

Comment ça se passe ? Concaténation de chaînes


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    apt
    apt est déconnecté
    Membre éclairé
    Inscrit en
    Mai 2002
    Messages
    867
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 867
    Par défaut Comment ça se passe ? Concaténation de chaînes
    Bonjour,

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    S = "Hello"
    S +=" World!"
    => Nom : new string +.png
Affichages : 447
Taille : 20,0 Ko

    Dans une concaténation de chaînes, comment se déroule le processus d'allocation de la nouvelle valeur en mémoire, sans effacer ni perdre le nom de la variable?

    La création de la nouvelle chaîne sera-t-elle enregistrée dans une variable temporaire avant de mettre à jour la valeur de S ?

    Merci d'avance.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Vous ne devez pas essayer de mélanger les différents niveaux d'abstractions, sinon vous allez juste vous perdre!

    Après si vous voulez voir ce qu'il se passe sous le capot, çà commence par:
    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
    >>> import dis
    >>> def f():
    ...     S = 'hello'
    ...     S += ' world'
    ...
    >>> dis.dis(f)
      2           0 LOAD_CONST               1 ('hello')
                  2 STORE_FAST               0 (S)
     
      3           4 LOAD_FAST                0 (S)
                  6 LOAD_CONST               2 (' world')
                  8 INPLACE_ADD
                 10 STORE_FAST               0 (S)
                 12 LOAD_CONST               0 (None)
                 14 RETURN_VALUE
    >>>
    et vous voyez que dans ce monde là, les choses du dessus se traduisent de façon bizarre.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par apt Voir le message
    Dans une concaténation de chaînes, comment se déroule le processus d'allocation de la nouvelle valeur en mémoire, sans effacer ni perdre le nom de la variable?
    La création de la nouvelle chaîne sera-t-elle enregistrée dans une variable temporaire avant de mettre à jour la valeur de S ?
    Déjà il faut éclater les opérateurs qui mixent opération et affectation( typiquement +=, -= etc) car ils se décomposent ("+=" devient "=" puis "+").
    Ainsi s+="World" se traduit par s=s + "World". Donc Python commence par calculer s + "World" (méthode "__add__" de l'objet "str") puis place le résultat de cette opération dans "s".
    Ne te reste qu'à regarder le source de Python, chercher l'objet "str" puis décortiquer sa méthode "__add__".
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    apt
    apt est déconnecté
    Membre éclairé
    Inscrit en
    Mai 2002
    Messages
    867
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 867
    Par défaut
    Bonjour wiztricks, Sve@r,

    @wiztricks : pas compris cette liste ?

    @Sve@r : Est-ce que l'adresse mémoire du premier s (s = "Hello") et la même pour le deuxième s (s = "Hello World!") ?

    Merci.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par apt Voir le message
    @Sve@r : Est-ce que l'adresse mémoire du premier s (s = "Hello") et la même pour le deuxième s (s = "Hello World!") ?
    Non. Lors de la nouvelle affectation, la mémoire précédente qui était dans le "s" est alors libérée. La nouvelle chaine est créée en mémoire puis affectée dans "s". Te suffit d'afficher hex(id(s)) à chaque étape et tu verras que les valeurs changent.

    Ensuite on peut mieux le voir si on crée son propre objet string qui montre ses étapes de création et de suppression...
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    class myStr(object):
    	def __init__(self, s):
    		print("__init__", repr(self), s)
    		self.__chaine=s
    	# __init__()
     
    	def __del__(self): print("__del__", repr(self), self.__chaine)
     
    	def __str__(self): return self.__chaine
     
    	def __add__(self, s): return myStr(self.__chaine+str(s))
    # class myStr
     
    s=myStr("Hello")
    print(s)
    s+=myStr("World")
    print(s)

    Déjà tu te rends compte que pour créer l'addition, je suis obligé de retourner un nouvel objet (sinon je ne pourrais pas écrire des expressions comme truc=myStr("a") + myStr("b")).

    Et donc au résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    __init__ <__main__.myStr object at 0x7f20c73a5860> Hello		# Première création
    Hello									# Affichage de la chaine "s"
    __init__ <__main__.myStr object at 0x7f20c73a54a8> World		# Seconde création
    __init__ <__main__.myStr object at 0x7f20c73a5470> HelloWorld		# Création du résultat de l'addition qui ira dans "s"
    __del__ <__main__.myStr object at 0x7f20c73a54a8> World			# Suppression de la seconde création devenue inutile
    __del__ <__main__.myStr object at 0x7f20c73a5860> Hello			# Suppression de la première création devenue inutile (puisque "s" est libérée)
    HelloWorld								# Affichage de la nouvelle chaine "s"
    __del__ <__main__.myStr object at 0x7f20c73a5470> HelloWorld		# Suppression du résultat de l'addition devenu inutile (puisque "s" est de nouveau libérée)
    Si on change juste s+=myStr("World") par ss=s+myStr("World") (donc on ne perd plus le premier "s"), le résultat...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    __init__ <__main__.myStr object at 0x7f5b4ec8a828> Hello		# Première création
    Hello									# Affichage de la chaine "s"
    __init__ <__main__.myStr object at 0x7f5b4ec8a470> World		# Seconde création
    __init__ <__main__.myStr object at 0x7f5b4ec8a400> HelloWorld		# Création du résultat de l'addition qui ira cettte fois dans "ss"
    __del__ <__main__.myStr object at 0x7f5b4ec8a470> World			# Suppression de la seconde création devenue inutile
    HelloWorld								# Affichage de la nouvelle chaine "ss"
    __del__ <__main__.myStr object at 0x7f5b4ec8a828> Hello			# Suppression de la première création devenue inutile (puisque "s" est libérée)
    __del__ <__main__.myStr object at 0x7f5b4ec8a400> HelloWorld		# Suppression du résultat de l'addition devenu inutile (puisque "ss" est libérée)
    ... et on voit que le premier "s" n'est supprimé qu'à la fin du programme. Maintenant... est-ce vraiment utile???

    Sinon un truc que là je pense bien plus important: les valeurs par défaut des paramètres d'une fonction qui sont crées non pas quand la fonction est appelée, mais quand la fonction est implémentée.

    Un exemple
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    class myObject(object):
    	def __init__(self): print("__init__", repr(self))
    	def __del__(self): print("__del__", repr(self))
    # class myObject
     
    def fct(n=myObject()):
    	print("entrée dans fct ", n)
     
    print(1)
    fct(123)
    print(2)
    fct()
    print(3)

    Et le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    __init__ <__main__.myObject object at 0x7fae6ae55828>		# L'objet est créé avant même que la fonction soit appelée
    1								# Affichage témoin
    entrée dans fct  123						# La fonction a été appelée avec un vrai paramètre, elle l'affiche
    2								# Affichage témoin
    entrée dans fct  <__main__.myObject object at 0x7fae6ae55828>	# La fonction a été appelée sans paramètre, elle affiche alors le paramètre par défaut créé au début du programme
    3								# Affichage témoin
    __del__ <__main__.myObject object at 0x7fae6ae55828>		# L'objet est supprimé avec la fonction quand le programme se termine
    C'est pour cela que ce genre de fonction...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def f(n, tab=[]):
    	tab.append(n)
    	return tab
    # f()
     
    print(f(1))
    print(f(2))
    print(f(3))
    ... peut causer des surprises...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [1]
    [1, 2]
    [1, 2, 3]
    !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par apt Voir le message
    @wiztricks : pas compris cette liste ?
    Quelle liste?

    On n'arrivera pas à vous expliquer quoi que ce soit si vous n'avez pas le minimum de bases pour comprendre.

    Il serait plus simple d'essayer d'expliquer quel problème vous cherchez à résoudre ou pourquoi vous posez cette question.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    apt
    apt est déconnecté
    Membre éclairé
    Inscrit en
    Mai 2002
    Messages
    867
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 867
    Par défaut
    Citation Envoyé par wiztricks
    Quelle liste?

    Celle-ci :


    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
    >>> import dis
    >>> def f():
    ...     S = 'hello'
    ...     S += ' world'
    ...
    >>> dis.dis(f)
      2           0 LOAD_CONST               1 ('hello')
                  2 STORE_FAST               0 (S)
     
      3           4 LOAD_FAST                0 (S)
                  6 LOAD_CONST               2 (' world')
                  8 INPLACE_ADD
                 10 STORE_FAST               0 (S)
                 12 LOAD_CONST               0 (None)
                 14 RETURN_VALUE 
    >>>

    Citation Envoyé par wiztricks
    pourquoi vous posez cette question.

    j'aimerais savoir comment python traite une concaténation (les étapes).


    Par exemple, utilise-t-il une nouvelle variable pour construire la nouvelle chaîne, avant de retourner la chaîne finale?


    La variable s pour cette chaine finale, est-ce la même que la chaîne de départ ou une nouvelle variable s ?


    La case mémoire allouée en premier temps pour la chaine "Hello", est-elle la même case mémoire pour la chaine "Hello World!"

    Sve@r

    Merci pour la démonstration, je vais essayer de comprendre tout ça !

  8. #8
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Règle numéro 1: Il n'y a pas de variable en Python.

    Lorsque tu fais s = "Hello" Python construit un objet str avec la valeur "Hello". Ensuite, si l'opération n'a pas échoué, il colle une étiquette avec la mention "s" sur cet objet.

    Donc l'objet c'est la str et non pas l'étiquette.

    La variable en tant que "boîte dont le contenu peut varier" est une notion totalement fausse en Python et tes questionnements reposent semble-t-il sur cette erreur.

    Si tu ajoutes s = "Bonjour" Python construit un objet str avec la valeur "Bonjour". Ensuite se souvient avoir déjà fait une étiquette avec un "s", l'enlève de l'objet str("Hello") et la colle sur le nouvel objet. Et lorsque tu fais une concaténation c'est pareil, tu construis un nouvel objet, dans une nouvelle zone mémoire mais c'est l'ancienne étiquette qui est réutilisée.

    Un même objet peut recevoir autant d'étiquettes que l'on veut. L'objet lui-même possède un compteur de référence pour gérer cela, lorsque ce compteur arrive à zéro il est effacé par un mécanisme appelé "Garbage collector". La mémoire libérée n'est pas nécessairement restituée au système, ça c'est de la cuisine interne.

    Ceci dit, ça ne dérange pas d'utiliser le terme variable, on comprend ce que tu veux dire, l'erreur est de voir ce "s" comme un objet ou une case mémoire.

Discussions similaires

  1. Réponses: 0
    Dernier message: 10/10/2016, 10h31
  2. Réponses: 3
    Dernier message: 19/09/2010, 03h50
  3. comment concaténer plusieurs chaînes de caractères
    Par saih_tam dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 11/02/2009, 11h42
  4. Comment concaténer des chaînes issues d'un fichier ini ?
    Par Neit_Sabes dans le forum Framework .NET
    Réponses: 10
    Dernier message: 27/09/2006, 09h28
  5. [XSLT 1.0] Concaténation de chaînes
    Par tofita_49 dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 25/07/2005, 18h34

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