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 :

Héritage et appel de fonctions d'une classe depuis une autre classe. [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut Héritage et appel de fonctions d'une classe depuis une autre classe.
    Bonjour,

    Je n'arrives pas à remplir des tableaux à l'aide d'une fonction en appelant celle-ci depuis une autre classe. J'ai lu pas mal de théorie, mais je rame total. Pourriez-vous, svp, m'indiquer concrètement ce qu'il faut que je change ? Parfois je comprends mieux à l'aide de code qu'à l'aide de la théorie...

    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    import random
     
    moves = ['rock', 'paper', 'scissors', 'lizard', 'spock']
     
    class Player:
    	def __init__(self):
    		self.record1 = []
    		self.record2 = []
     
    	#fonction qui joue un mouvement au hasard	
    	def move1(self):
    		return random.choice(moves)
     
    	#Function pour stocker les mouvements des deux joueurs
    	def learn(self, move1, move2):
    		self.record1.append(move1)
    		self.record2.append(move2)
    		return self.record1
     
    #Class qui joue le mouvement précédent du joueur adverse
    class ReflectPlayer(Player):
    	def __init__(self):
    		super().__init__()
    		self.record1 = []
    		self.record2 = []		
    		self.move = None		
     
    	#Function joue le mouvement précédent du joueur adverse	
    	def ReflectMove(self):
    		move = ""
    		l = len(self.record1)
    		if l == 0:
    			move = "rock"
    		else:
    			move = self.record1[len(self.record1) - 1]
    		self.move = move
    		return self.move 
     
    	#Function pour stocker les mouvements des deux joueurs
    	def learn(self, move1, move2):
    		self.record1.append(move1)
    		self.record2.append(move2)
    		return self.record1
     
     
    class Game(ReflectPlayer):
    	def __init__(self, p1, p2):
    		super().__init__()
    		self.p1 = p1
    		self.p2 = p2
     
    	def play_round(self):
    		move1 = self.p1.move1()
    		move2 = self.p2.ReflectMove()		
    		print(f"You played : {move1}")
    		print(f"Your opponent played : {move2}")
    		self.p1.learn(move1, move2) # appel fonctions pour remplir les tableaux dans les autres classes
    		self.p2.learn(move2, move1) # appel fonctions pour remplir les tableaux dans les autres classes
    		print(ReflectPlayer().record1)
    		print(ReflectPlayer().record1)
     
    	#Function for playing multiple games
    	def play_game(self):					
    		print("\nGame start! \n")
    		for round in range(3):
    			print(f"Round {round}: \n")
    			self.play_round()					
    		print("Game over! \n")
     
     
    # programme principal
     
    g = Game(Player(), ReflectPlayer())
    g.play_game()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    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 743
    Par défaut
    Salut,

    Relisez attentivement les lignes 59, 60:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	print(ReflectPlayer().record1)
    	print(ReflectPlayer().record1)
    Et si vous ne comprenez pas pourquoi c'est n'importe quoi, ouvrez un tuto.

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

  3. #3
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut J'ai mis ces deux print pour voir le contenu de mes tableaux, mais la fonction "learn" ne fonctionne pas.
    Citation Envoyé par wiztricks Voir le message
    Salut,

    Relisez attentivement les lignes 59, 60:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	print(ReflectPlayer().record1)
    	print(ReflectPlayer().record1)
    Et si vous ne comprenez pas pourquoi c'est n'importe quoi, ouvrez un tuto.

    - W
    J'ai mis ces deux print pour voir le contenu de mes tableaux en test, mais la fonction "learn" ne fonctionne pas. Cela dit, merci pour votre réponse, elle m'aide énormément !!

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    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 743
    Par défaut
    Citation Envoyé par PythonJaune Voir le message
    J'ai mis ces deux print pour voir le contenu de mes tableaux en test, mais la fonction "learn" ne fonctionne pas.
    Ben c'est la que çà affiche des listes vides non?

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

  5. #5
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut
    Je crois qu'on ne s'est pas compris. Je sais bien que les tableaux ne sont pas remplis, c'est exactement le problème que j'ai. Ils devraient se remplir à l'aide de la fonction "learn" qui se trouve dans les deux autres classes qui sont : Player et ReflectPlayer. Je pense qu'il s'agit d'un problème de liaison des classes ou d'héritage qui fait que lorsque j'appelle la fonction "learn", depuis ma classe Game, elle ne s'exécute pas. J'ai beau parcourir les tutos, je planche totalement. C'est pourquoi je pose la question. Si vous exécutez le code, vous verrez que la classe qui est sensée répliquer les mouvements de l'autre joueur, à partir du second tour, ne le fait pas.

    je reposte le code sans les deux prints :

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    import random
     
    moves = ['rock', 'paper', 'scissors', 'lizard', 'spock']
     
    class Player:
    	def __init__(self):
    		self.record1 = []
    		self.record2 = []
     
    	#fonction qui joue un mouvement au hasard	
    	def move1(self):
    		return random.choice(moves)
     
    	#Function pour stocker les mouvements des deux joueurs
    	def learn(self, move1, move2):
    		self.record1.append(move1)
    		self.record2.append(move2)
    		return self.record1
     
    #Class qui joue le mouvement précédent du joueur adverse
    class ReflectPlayer(Player):
    	def __init__(self):
    		super().__init__()
    		self.record1 = []
    		self.record2 = []		
    		self.move = None		
     
    	#Function joue le mouvement précédent du joueur adverse	
    	def ReflectMove(self):
    		move = ""
    		l = len(self.record1)
    		if l == 0:
    			move = "rock"
    		else:
    			move = self.record1[len(self.record1) - 1]
    		self.move = move
    		return self.move 
     
    	#Function pour stocker les mouvements des deux joueurs
    	def learn(self, move1, move2):
    		self.record1.append(move1)
    		self.record2.append(move2)
    		return self.record1
     
     
    class Game(ReflectPlayer):
    	def __init__(self, p1, p2):
    		super().__init__()
    		self.p1 = p1
    		self.p2 = p2
     
    	def play_round(self):
    		move1 = self.p1.move1()
    		move2 = self.p2.ReflectMove()		
    		print(f"You played : {move1}")
    		print(f"Your opponent played : {move2}")
    		self.p1.learn(move1, move2) # appel fonctions pour remplir les tableaux dans les autres classes
    		self.p2.learn(move2, move1) # appel fonctions pour remplir les tableaux dans les autres classes
     
     
    	#Function for playing multiple games
    	def play_game(self):					
    		print("\nGame start! \n")
    		for round in range(3):
    			print(f"Round {round}: \n")
    			self.play_round()					
    		print("Game over! \n")
     
     
    # programme principal
     
    g = Game(Player(), ReflectPlayer())
    g.play_game()

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    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 743
    Par défaut
    Citation Envoyé par PythonJaune Voir le message
    Je pense qu'il s'agit d'un problème de liaison des classes ou d'héritage qui fait que lorsque j'appelle la fonction "learn", depuis ma classe Game, elle ne s'exécute pas.
    Quand vous faites ce genre d'hypothèse, ajoutez un "print" dans le corps de la méthode: c'est facile à tester et vous aurez la réponse à votre question.
    Profitez en pour afficher ce qu'elle reçoit en paramètre et vérifier que c'est cohérent (avec ce que vous attendez).
    Puis si çà vous dépasse encore, simplifiez: virez tout ce qui ne sert à rien (et il y en a des tonnes).
    Python ne fait que ce que vous lui avez demandé d'exécuter et si çà ne se passe pas comme vous l'attendez, c'est que quelque part, vous avez une erreur de logique (la logique du jeu qui est dans votre tête).

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

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par PythonJaune Voir le message
    moves = ['rock', 'paper', 'scissors', 'lizard', 'spock']
    Ah ? tu as suivi mon idée et rajouté les coups "à la Sheldon"

    Citation Envoyé par PythonJaune Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	#fonction qui joue un mouvement au hasard	
    	def move1(self):
    		return random.choice(moves)
    C'est effectivement le meilleur choix. En effet, la meilleure stratégie pour gagner au shifoumi est de jouer au hasard

    Citation Envoyé par PythonJaune Voir le message
    #Class qui joue le mouvement précédent du joueur adverse
    Ca je comprends moins. Ok adopter comme stratégie de jouer le dernier coup du joueur adverse je veux bien (mais s'il s'en aperçoit t'es mort) mais créer une classe pour ça ???
    T'as la liste des coups des deux joueurs. Tu veux jouer le dernier coup adverse tu joues simplement record2[-1] !!!

    Une classe c'est un truc qui doit pouvoir faire des actions. Là quelle action tu veux faire à part "sortir le dernier coup stocké" qui est un truc directement accessible via son indice ?
    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]

  8. #8
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut
    Salut Steve@r et merci pour ta réponse.

    En fait, je le fais dans le cadre d'un projet pour un cours. On me demande de créer 4 classes pour 4 stratégies, et la seule que je n'arrive pas à faire fonctionner c'est celle-là (reflect player). Cette classe (un peu con certes) est sensée jouer ou répliquer le coup antérieur de l'adversaire. Mais je n'y arrives pas. Je planche dessus depuis très longtemps... si tu exécutes le code, tu verras que le joueur "oponent" devrait jouer la première fois rock et ensuite répliquer ton mouvement. Et ça ne fonctionne pas. Je suis débutant..... J'ai mis des "print" partout dans ma fonction pour essayer de voir ce qui ne va pas, mais que dalle....

  9. #9
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut
    Et au fait, oui, j'ai suivi ta recommendation car à la fin de l'énoncé du projet il est écrit que l'on peut faire varier le jeu pour une meilleure appréciation.

  10. #10
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 743
    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 743
    Par défaut
    Citation Envoyé par PythonJaune Voir le message
    Et au fait, oui, j'ai suivi ta recommendation car à la fin de l'énoncé du projet il est écrit que l'on peut faire varier le jeu pour une meilleure appréciation.
    Si vous avez ajouté un "print" à learn vous devriez constater qu'à chaque appel c'est "rock" s'ajoute à la liste self.record1: comme le coup suivant est donné par le dernier de la liste, çà joue toujours "rock", normal! Mais ce n'est pas (toujours) ce qu'à joué l'adversaire.

    Python, lui, ne fait qu'exécuter des instructions ce que vous pensez/voulez, il s'en fout.
    Et le gros travail du programmeur, c'est pas écrire des lignes mais savoir se relire et questionner son code pour s'assurer qu'il va bien faire ce qu'il attend.

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

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Ok, j'ai testé ton code.
    Déjà il faut que ton objet "Player" hérite de "object". Ou alors c'est parce que mon Python (3.4.2) est trop ancien que chez-moi ça ne veut pas le faire sans ça.

    Ensuite tu dis que "learn" de ReflectPlayer n'est pas appelé => moi j'ai mis un "print" et je vois le print s'afficher donc il est bien appelé.

    Maintenant, puisque ReflectPlayer hérite de Player et que Player possède déjà une méthode "learn" pourquoi tu la redéfinis à l'identique dans "ReflectPlayer" ? Supprime-là puisqu'elle fait la même chose (ça sert à ça l'héritage). Idem pour "record1" et "record2" qui existent déjà dans la classe mère "Player".

    Sinon tu as raisonné à l'envers (enfin d'après ce que je comprends). Parce que du point de vue du joueur adverse (donc celui qui est de la classe "ReflectPlayer"), le coup de son adversaire est stocké dans "record2", pas "record1" !!!
    Donc la méthode "ReflectMove" doit renvoyer le dernier coup stocké dans "record2". Ca t'apprendra à choisir tes noms de variable avec plus d'intelligence (tu aurais appelé ça "myMove" et "opponentMove" tu aurais de suite trouvé !!!)

    Maintenant les trucs inutiles
    • inutile de stocker le coup joué dans "self.move"
    • inutile que "learn" renvoie un truc
    • pas besoin d'un __init__ dans ReflectPlayer qui ne fait juste qu'appeler le __init__ de Player => on le supprime et l'héritage fait le reste
    • la fonction "ReflectMove" de la classe "ReflectPlayer" pourrait s'appeler "move" pour uniformiser (quand tu auras 4 objets ayant chacun leur stratégie et que tu en choisiras une, tu n'auras pas besoin de changer le nom de la méthode appelée)
    • Game n'a pas besoin d'hériter de Player ou de ReflectPlayer. L'héritage c'est un peu comme dire "ceci est un cas particulier de cela" => une voiture est un cas particulier de véhicule. Le jeu n'est certainement pas un cas particulier d'un joueur (à la limite tu aurais dit qu'un joueur était un cas particulier du jeu j'aurais mieux accepté)


    Il y a aussi des trucs dont je m'explique mal l'utilité
    • pourquoi stocker ses propres coups
    • pourquoi stocker tous les coups joués (tous les siens et tous ceux de l'adversaire)
    • pourquoi chaque joueur stocke tous les coups (redondance) alors que les coups pourraient être stockés par le jeu lui-même (donc une seule fois) et les deux joueurs y auraient librement accès

    Mais bon, pour les deux premiers je me dis que peut-être ça pourra servir plus tard et pour le 3° ça devient un trop grand changement (surtout que si on supprime ça alors l'objet "Player" ne contient plus rien du tout) donc j'ai laissé ces points inchangés. Ce qui donne donc ceci
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    import random
     
    # Objet qui gère le joueur principal
    class Player(object):
    	def __init__(self):
    		self.record1=[]
    		self.record2=[]
    	# __init__()
     
    	# Fonction qui gère le mouvement du joueur principal => un mouvement au hasard	
    	def move(self):
    		return random.choice(Game.moves)
     
    	# Fonction pour stocker les mouvements des deux joueurs
    	def learn(self, move1, move2):
    		self.record1.append(move1)
    		self.record2.append(move2)
    	# __learn__()
    # class Player
     
    # Objet qui gère un adversaire ayant pour stratégie de répéter le dernier coup du joueur principal
    class ReflectPlayer(Player):
    	# Fonction qui joue le mouvement correspondant à la stratégie de l'objet (dernier coup joué par l'adversaire)
    	def move(self):
    		return self.record2[-1] if self.record2 else Game.moves[0]
    # class ReflectPlayer
     
    # Objet qui gère le jeu
    class Game(object):
    	moves=['rock', 'paper', 'scissors', 'lizard', 'spock']
     
    	def __init__(self, p1, p2):
    		super(Game, self).__init__()
    		self.p1 = p1
    		self.p2 = p2
    	# __init__()
     
    	def play_round(self):
    		move1 = self.p1.move()
    		move2 = self.p2.move()		
    		print("You played : %s" % move1)
    		print("Your opponent played : %s" % move2)
    		self.p1.learn(move1, move2) # appel fonctions pour remplir les tableaux dans les autres classes
    		self.p2.learn(move2, move1) # appel fonctions pour remplir les tableaux dans les autres classes
    	# play_round()
     
    	# Function for playing multiple games
    	def play_game(self):					
    		print("\nGame start! \n")
    		for round in range(3):
    			print("Round %d: \n" % round)
    			self.play_round()					
    		# for
    		print("Game over! \n")
    	# play_game()
    # class Game
     
    # Programme principal
    g = Game(Player(), ReflectPlayer())
    g.play_game()
    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]

  12. #12
    Membre régulier
    Homme Profil pro
    Apprentissage python
    Inscrit en
    Novembre 2018
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Apprentissage python

    Informations forums :
    Inscription : Novembre 2018
    Messages : 10
    Par défaut
    Salut Steve@r et merci pour ta réponse.

    En effet, je constate que je me suis bien trop compliqué la vie, et que du coup j'ai ajouté plein de trucs inutiles. En gros, je me suis bien paumé. Et sincèrement, si tu ne m'avais pas éclairé sur ces sujets, j'aurais pu tourner en boucle très longtemps.

    Merci pour la lumière apportée sur tous les points.

    Meilleures salutations.

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

Discussions similaires

  1. Appel d'une methode depuis d'autre class
    Par giraud vias dans le forum C#
    Réponses: 3
    Dernier message: 28/12/2017, 14h17
  2. Appeler une méthode d'une appli depuis une autre sans toucher à son code
    Par Omegnight dans le forum Langages de programmation
    Réponses: 4
    Dernier message: 10/03/2016, 18h58
  3. Réponses: 3
    Dernier message: 09/10/2015, 17h16
  4. Appel de fonction d'un UserControl depuis une Form
    Par belzeluc dans le forum Windows Forms
    Réponses: 7
    Dernier message: 14/09/2007, 16h42
  5. Réponses: 4
    Dernier message: 20/03/2007, 14h53

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