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 :

Modifier un objet


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut Modifier un objet
    Bonjour,

    j'ai une classe qui prend un objet et lui ajoute des propriétés en modifiant son MRO.
    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
     
    # objet quelconque
    class UnObjet:
     
        def __init__(self,x):
            self.x = x
            print('foo')
     
     
     
    # classe qui modifie un objet
    class Mod:
     
        def __new__(cls,objet,*args):
            objet.__class__ = type('**',(cls,objet.__class__),{})
            return objet
     
        def __init__(self,*args):
            print('mod')
     
        @property
        def y(self):
            return self.x + 2
     
     
     
    #classe qui cree un objet et le modifie
    class Mod2(Mod):
     
        #ici il faut surcharger __new__
        def __new__(cls,x,z):
            instance = Mod.__new__(cls,UnObjet(x))
            return instance
     
        def __init__(self,x,z):
     
            Mod.__init__(self)
            print('mod2')
     
        #d'autres propriétés ici
     
     
     
     
    objet = Mod(UnObjet(5))
    print(objet.y)
    #foo
    #mod
    #7
    objet = Mod2(8,3)
    print(objet.y)
    #foo
    #mod
    #10
    y a-t-il une façon de faire ceci sans passer par __new__ ? Car les classes qui héritent de Mod doivent aussi surcharger __new__.
    la seule solution qui me vient à l'esprit c'est de passer par une fonction qui retourne une instance.
    qu'en pensez-vous ?

    Merci.

  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,

    Citation Envoyé par josmiley Voir le message
    y a-t-il une façon de faire ceci sans passer par __new__ ? Car les classes qui hérites de Mod doivent aussi surcharger __new__.
    la seule solution qui me vient à l'esprit c'est de passer par une fonction qui retourne une instance.
    Le code modifie l'attribut __class__ de l'instance d'UnObjet avec une nouvelle classe ** qui hérite de Mod et UnObjet.
    Ce qui est discutable est que le __new__ de Mod retourne un ** plutôt qu'un Mod: on cannibalise une interface système existante pour faire quelque chose qui pourrait se faire très bien ailleurs (et donc à faire autrement... d'où peut être la question).

    Ceci dit, en POO, le changement de comportement d'un objet est généralement traité avec le state pattern qui fait cela sans bidouiller l'attribut système __class__ (option qui n'est pas disponible dans beaucoup de langages objets)...
    Personnellement quand je le fais, je garde quand même l'ossature du pattern (ça permet de documenter la bidouille).

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

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    J'ai beau lire et relire les exemples que j'ai trouvé sur le state pattern , je ne vois pas comment cela s'applique ici. Mais il est probable que je n'ai rien compris

  4. #4
    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 josmiley Voir le message
    J'ai beau lire et relire les exemples que j'ai trouvé sur le state pattern , je ne vois pas comment cela s'applique ici. Mais il est probable que je n'ai rien compris
    Il faudrait reprendre le state pattern basique... puis le faire évoluer petit à petit vers.
    Ou bien on reformule le besoin initial avec... mais comme on l'ignore, refaire le boulot de conception risque de voir surgir d'autres solutions.

    note: Ceux qui connaissent bien Python reformulent un problème avec les structures de bases du langage (liste, dict, ...). Si je pense POO, je reformule avec des patterns. Ce qui est un exercice bien en amont du codage (et qui n'a rien à voir avec un langage particulier).

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

  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
    Bonjour
    Citation Envoyé par josmiley Voir le message
    j'ai une classe qui prend un objet et lui ajoute des propriétés en modifiant son MRO.
    Je ne vois pas trop, dans ton exemple, où tu rajoutes des propriétés. Tu parles de "y"? Mais "y" ce n'est pas une propriété, c'est un getter !!!

    Citation Envoyé par josmiley Voir le message
    la seule solution qui me vient à l'esprit c'est de passer par une fonction qui retourne une instance.
    qu'en pensez-vous ?
    Peut-être les métaclasses?
    Voici un exemple complet. La métaclasse "custom" récupère des classes pour les customiser. Et pour chaque classe récupérée, elle transforme chaque méthode "xxx", quelle qu'elle soit, en méthode nommée "custom_xxx"

    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
    #!/usr/bin/env python3
    # coding: utf-8
     
    # La fonction de customisation
    # Chaque méthode de la classe customisée sera nommée "custom_<nom de la méthode>"
    def custom(cls, parents, attr):
    	# Un petit affichage préalable pour montrer ce qui se passe…
    	print("custom: cls=%s, parents=%s, attr=%s" % (cls, parents, attr))
     
    	# Elle commence par créer le dictionnaire des nouveaux attributs
    	nouveaux_attr=dict()
     
    	# Puis elle traite les méthodes de la classe reçue en paramètre
    	for (k, v) in attr.items():
    		# La nouvelle clef est créée selon le nom de la méthode d'origine (si celle-ci n’est pas une méthode spéciale)
    		new_k=("custom_" if not k.startswith("__") else "") + k
    		print(k, v, new_k)
     
    		# Le code de la méthode d'origine est recopié dans le nouveau dictionnaire avec son nouveau nom
    		nouveaux_attr[new_k]=v
    	# for
    	print(nouveaux_attr)
     
    	# La fonction renvoie une nouvelle classe créée dynamiquement depuis la classe reçue
    	return type(cls, parents, nouveaux_attr)
    # custom()
     
    # L’objet "toto" qui sera customisé par la fonction
    class toto(metaclass=custom):
    	def affich(self):
    		print("my name is toto!!!")
    # class toto
     
    # L’objet "titi" qui sera customisé par la fonction
    class titi(metaclass=custom):
    	def print(self):
    		print("my name is titi!!!")
    # class titi
     
    # Test de la customisation
    to=toto()
    ti=titi()
    to.custom_affich()		# La méthode "affich" d'origine a été renommée en "custom_affich"
    ti.custom_print()		# La méthode "print" d'origine a été renommée en "custom_print"
    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
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Je ne vois pas trop, dans ton exemple, où tu rajoutes des propriétés. Tu parles de "y"? Mais "y" ce n'est pas une propriété, c'est un getter !!!


    Peut-être les métaclasses?
    Voici un exemple complet. La métaclasse "custom" récupère des classes pour les customiser. Et pour chaque classe récupérée, elle transforme chaque méthode "xxx", quelle qu'elle soit, en méthode nommée "custom_xxx"

    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
    #!/usr/bin/env python3
    # coding: utf-8
     
    # La fonction de customisation
    # Chaque méthode de la classe customisée sera nommée "custom_<nom de la méthode>"
    def custom(cls, parents, attr):
    	# Un petit affichage préalable pour montrer ce qui se passe…
    	print("custom: cls=%s, parents=%s, attr=%s" % (cls, parents, attr))
     
    	# Elle commence par créer le dictionnaire des nouveaux attributs
    	nouveaux_attr=dict()
     
    	# Puis elle traite les méthodes de la classe reçue en paramètre
    	for (k, v) in attr.items():
    		# La nouvelle clef est créée selon le nom de la méthode d'origine (si celle-ci n’est pas une méthode spéciale)
    		new_k=("custom_" if not k.startswith("__") else "") + k
    		print(k, v, new_k)
     
    		# Le code de la méthode d'origine est recopié dans le nouveau dictionnaire avec son nouveau nom
    		nouveaux_attr[new_k]=v
    	# for
    	print(nouveaux_attr)
     
    	# La fonction renvoie une nouvelle classe créée dynamiquement depuis la classe reçue
    	return type(cls, parents, nouveaux_attr)
    # custom()
     
    # L’objet "toto" qui sera customisé par la fonction
    class toto(metaclass=custom):
    	def affich(self):
    		print("my name is toto!!!")
    # class toto
     
    # L’objet "titi" qui sera customisé par la fonction
    class titi(metaclass=custom):
    	def print(self):
    		print("my name is titi!!!")
    # class titi
     
    # Test de la customisation
    to=toto()
    ti=titi()
    to.custom_affich()		# La méthode "affich" d'origine a été renommée en "custom_affich"
    ti.custom_print()		# La méthode "print" d'origine a été renommée en "custom_print"
    salut,
    pour la première question j'ai donner un exemple simple vite fait.
    pour les metaclass, ça implique de modifier le code des classes "class toto(metaclass=custom):", et que la customisation s'applique à toutes les instances non ?

    voilà une version avec fonction qui retourne une instance; finalement plus simple que de surcharger __new__.
    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
     
     
    # objet quelconque
    class UnObjet:
     
        def __init__(self,x):
            self.x = x
            print('foo')
     
     
    # classe qui modifie un objet
    class Mod:
     
        def __new__(cls,objet,*args):
            objet.__class__ = type('**',(cls,objet.__class__),{})
            return objet
     
        def __init__(self,*args):
            print('mod')
     
        @property
        def y(self):
            return self.x + 2
     
     
     
    def Mod2(x,z): 
     
        #classe qui cree un objet et le modifie
        class Mod2_(Mod):
     
            def __init__(self,objet,z):
                Mod.__init__(self)
                print('mod2')
                print('z =',z)
     
            #d'autres propriétés ici
     
        objet = UnObjet(x)
        return Mod2_(objet,z)
     
     
    objet = Mod2(8,3)
    print(objet.y)
    #foo
    #mod
    #mod2
    #z = 3
    #10

  7. #7
    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 josmiley Voir le message
    pour la première question j'ai donner un exemple simple vite fait.
    Effectivement j'avais pas fait attention que tu passes UnObjet. Toutefois ce n'est pas une vraie modif. Tu ne fais que créer un objet "Mod" contenant les attributs de "UnObjet" et un getter. A la limite tu hériterais de "UnObjet" ça ferait pareil.

    Citation Envoyé par josmiley Voir le message
    pour les metaclass, ça implique de modifier le code des classes "class toto(metaclass=custom):", et que la customisation s'applique à toutes les instances non ?
    Ah effectivement. On n'a même pas à parler d'instance tellement c'est implicite. C'est la classe elle-même qui est modifiée dans sa définition ; les instances seront donc automatiquement instances de la classe modifiée. Mais je pensais que c'était ce que tu voulais (qui dit "modifier un objet" dit par transitivité "modifier toutes les instances de l'objet")...
    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 Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Oui en héritant de UnObjet ça serait pareil , mais c'était pour l'exemple ,en fait ça peut être n'importe quel objet .

    Plus concrètement j'ai différents objets graphiques,boutons ,fenêtres ,image, etc...
    En passant cet objet en argument d'instanciation à une classe Cursor celui-ci devient draggable.
    Ça peut servir entre autres à faire differents types de toggleswitch.
    En gros , ma logique c'est pas, "fait un toggleswitch avec ce bouton", mais plutôt "prend n'importe quel objet et fais en un toggleswitch".

Discussions similaires

  1. [POO] Modifier un objet [références]
    Par MorganStern dans le forum Langage
    Réponses: 11
    Dernier message: 04/05/2007, 12h44
  2. Réponses: 6
    Dernier message: 08/12/2006, 03h13
  3. [vb.net]modifier un objet dans un arrayList
    Par Golzinne dans le forum Windows Forms
    Réponses: 4
    Dernier message: 17/10/2006, 13h23
  4. Réponses: 6
    Dernier message: 21/05/2006, 20h37
  5. Modifier un objet dhtml
    Par roger_owc dans le forum ASP
    Réponses: 1
    Dernier message: 26/08/2005, 12h52

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