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 :

Génération d'un objet à partir de différentes classes [Python 2.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur backend (python)
    Inscrit en
    Mai 2014
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur backend (python)

    Informations forums :
    Inscription : Mai 2014
    Messages : 77
    Par défaut Génération d'un objet à partir de différentes classes
    Bonjour,

    Tout d'abord, je tiens à préciser que je travail sur du python 2.7 (Pas par libre choix, rassurez vous).

    Mon problème est le suivant, j'ai besoin de générer une instance d'objet avec un mix d'attributs défini dans d'autres classes et des attributs à passer directement à la création de mon objet.
    La partie ou je bloque est la récupération des attributs depuis les autres classes de manière élégante sans avoir à faire une forêt de if qui va très vite devenir illisible.
    Ce n'est peut-être pas très clair donc voici un exemple :

    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
    75
    76
    77
     
    class ComponentCommand1(object):
        mk_cmd = 'mkcomponent'
        rm_cmd = 'rmcomponent'
     
    class ComponentCommand2(object):
        mk_cmd = 'mkothercomponent'
        rm_cmd = 'rmothercomponent'
     
    class ComponentArgs1():
        args = {
            'name': '',
            'attr1': True,
            'attr2' : '0',
            'attr3' : '2%',
            'attr4' : '',
            'attr5': ''
        }
     
    class ComponentArgs2():
        args = {
            'name': '',
            'attr1': True,
            'attr2' : '0',
            'attr3' : '0%',
            'attr4' : '',
            'attr5': ''
        }
     
    class ComponentArgs3():
        args = {
            'name': '',
            'attr1': False,
            'attr2' : '0',
            'attr4' : '',
            'attr5': ''
        }
     
    class ComponentArgs4():
        args = {
            'name': '',
            'attr1': True,
            'attr2' : '0',
            'attr6' : False,
            'attr7': ''
        }
     
    class Component(object):
     
        def __init__(self, external_attr1, external_attr2):
            self.external_attr1 = external_attr1
            self.external_attr2 = external_attr2
     
    def component_builder(ext_attr1, ext_attr2, command_choice, attr_choice):
        component = Component(ext_attr1, ext_attr2)
     
        if command_choice == 1:
            component.mk_cmd = ComponentCommand1.mk_cmd
            component.rm_cmd = ComponentCommand1.rm_cmd
        elif command_choice == 2:
            component.mk_cmd = ComponentCommand2.mk_cmd
            component.rm_cmd = ComponentCommand2.rm_cmd
        else:
            raise ValueError('Command_choice unknown.')
     
        if attr_choice == 1:
            component.args = ComponentArgs1.args
        elif attr_choice == 2:
            component.args = ComponentArgs2.args
        elif attr_choice == 3:
            component.args = ComponentArgs3.args
        elif attr_choice == 4:
            component.args = ComponentArgs4.args
        else:
            raise ValueError('Attr_choice unknown.')
     
        return component
    J'ai regarder du coté des designs patterns, et le builder semble correspondre à ce que je souhaiterais faire, mais j'ai du mal à voir une bonne façon de l'implémenter, et je trouve ma fonction component_builder très peu flexible et difficilement maintenable une fois que j'aurais beaucoup d'objets différents à y intégrer.

    Merci d'avance, et bonne journée

  2. #2
    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 Takka Voir le message
    Tout d'abord, je tiens à préciser que je travail sur du python 2.7 (Pas par libre choix, rassurez vous).
    On est rassurés mais en même temps très tristes pour toi. Parce que plus tu attends pour basculer P3, plus ça te fera mal au luc. Sans parler des innombrables librairies qui évoluent définitivement dans P3. Le jour où tu auras besoin de la libTruc qui ne sera dispo que sous P3, tu comprendras ta douleur. C'est d'ailleurs cette raison qui m'a fait basculer en 2019.
    Ok ce n'est pas ton choix (donc celui d'un cheffaillon quelconque) mais toi, en tant que dev Python confirmé, il est de ton devoir de le sensibiliser aux soucis que sa décision provoquera à plus ou moins long terme parce que quand ça arrivera, ce sera la cascade d'emmerdes.

    Citation Envoyé par Takka Voir le message
    Mon problème est le suivant, j'ai besoin de générer une instance d'objet avec un mix d'attributs défini dans d'autres classes et des attributs à passer directement à la création de mon objet.
    La partie ou je bloque est la récupération des attributs depuis les autres classes de manière élégante sans avoir à faire une forêt de if qui va très vite devenir illisible.
    Ce n'est peut-être pas très clair donc voici un exemple :

    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
    class ComponentCommand1(object):
        mk_cmd = 'mkcomponent'
        rm_cmd = 'rmcomponent'
     
    class ComponentCommand2(object):
        mk_cmd = 'mkothercomponent'
        rm_cmd = 'rmothercomponent'
     
    class ComponentArgs1():
        args = {
            'name': '',
            'attr1': True,
            'attr2' : '0',
            'attr3' : '2%',
            'attr4' : '',
            'attr5': ''
        }
     
    class ComponentArgs2():
        args = {
            'name': '',
            'attr1': True,
            'attr2' : '0',
            'attr3' : '0%',
            'attr4' : '',
            'attr5': ''
        }
    Hum... Je n'arrive pas encore à bien voir comment tu articules ça. Il faudrait que tu appelles réellement componant_builder avec des valeurs à toi que je voies ce qui en sort.

    Mais reprenons les bases. Pourquoi les valeurs "mk_cmd" et "rm_cmd" sont dans des classes? Tu n'aurais pas avantage à plutôt les ranger dans un simple dict ??? Une classe c'est un truc qui a des valeurs et aussi qui les utilise. Si tu te contentes de simplement stocker des valeurs, la classe devient immédiatement moins pertinente.
    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
    config={
    	"command" : {
    		"command1" : {
    			"mk_cmd" : "mkcomponent",
    			"rm_cmd" : "rmcomponent",
    		},
    		"command2" : {
    			"mk_cmd" : "mkothercomponent",
    			"rm_cmd" : "rmothercomponent",
    		},
    	},
    	"args" : {
    		"args1" : {
    			"name" : "",
    			"attr1" : False,
    			"attr2" : 0,
    		},
    		"args2" : {
    			"name" : "",
    			"attr1" : True,
    			"attr2" : 1,
    		},
    	},
    }
    Ensuite, te suffit de passer config["command"]["commandX"] et config["args"]["argsY"] à ta vraie classe qui récupèrera alors ce dont elle a besoin...

    Si maintenant il faut des classes parce que tu as des valeurs mais aussi parce que tu les utilises, alors tu n'as aucune raison de séparer ComponentCommand1 et CompnentCommand2 (déjà le simple fait de nommer une variable ou une classe "truc1" et "truc2" montre un problème de conception). Si je dois travailler sur des véhicules, je ne créerai pas un objet "vehiculeRouge" et "vehiculeBleu" mais un objet "vehicule" qui contient un attribut "couleur" qui sera rouge ou bleu.

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ComponentCommand(object):
    	config={
    		"command1" : {
    			"mk_cmd" : "mkcomponent",
    			"rm_cmd" : "rmcomponent",
    		},
    		"command2" : {
    			"mk_cmd" : "mkothercomponent",
    			"rm_cmd" : "rmothercomponent",
    		},
    	}
    Ce qui ne change pas grand chose ensuite à la façon de l'utiliser...

    Citation Envoyé par Takka Voir le message
    mais j'ai du mal à voir une bonne façon de l'implémenter, et je trouve ma fonction component_builder très peu flexible et difficilement maintenable une fois que j'aurais beaucoup d'objets différents à y intégrer.
    A ce sujet je ne peux que te répéter la citation de Tim Peters: Si vous vous demandez si vous avez besoin des métaclasses, alors ce n’est pas le cas. Les gens qui en ont vraiment besoin le savent avec certitude et n’ont pas besoin d’explications sur la raison.
    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]

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur backend (python)
    Inscrit en
    Mai 2014
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur backend (python)

    Informations forums :
    Inscription : Mai 2014
    Messages : 77
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour
    On est rassurés mais en même temps très tristes pour toi. Parce que plus tu attends pour basculer P3, plus ça te fera mal au luc. Sans parler des innombrables librairies qui évoluent définitivement dans P3. Le jour où tu auras besoin de la libTruc qui ne sera dispo que sous P3, tu comprendras ta douleur. C'est d'ailleurs cette raison qui m'a fait basculer en 2019.
    Malheureusement, je suis arrivé récemment, et il y a une très grosse base de code en python2, sans que j'ai de temps alloué pour tout migrer en ptyhon3. Mais si je pouvais, c'est la première chose que je ferais

    Citation Envoyé par Sve@r Voir le message
    Hum... Je n'arrive pas encore à bien voir comment tu articules ça. Il faudrait que tu appelles réellement componant_builder avec des valeurs à toi que je voies ce qui en sort.

    Mais reprenons les bases. Pourquoi les valeurs "mk_cmd" et "rm_cmd" sont dans des classes? Tu n'aurais pas avantage à plutôt les ranger dans un simple dict ??? Une classe c'est un truc qui a des valeurs et aussi qui les utilise. Si tu te contentes de ranger des valeurs, la classe devient immédiatement moins pertinente...
    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
    config={
    	"command" : {
    		"command1" : {
    			"mk_cmd" : "mkcomponent",
    			"rm_cmd" : "rmcomponent",
    		},
    		"command2" : {
    			"mk_cmd" : "mkothercomponent",
    			"rm_cmd" : "rmothercomponent",
    		},
    	},
    	"args" : {
    		"args1" : {
    			"name" : "",
    			"attr1" : False,
    			"attr2" : 0,
    		},
    		"args2" : {
    			"name" : "",
    			"attr1" : True,
    			"attr2" : 1,
    		},
    	},
    }
    Ensuite, te suffit de passer config["command"]["commandX"] et config["args"]["argsY"] à ta vraie classe qui récupèrera alors ce dont elle a besoin...
    Pour ce qui est de l'utilisation de classe et non de dictionnaire, c'est plus en terme de lisibilité, avoir un gros dictionnaire avec beaucoup de données dedans est quelque chose que je trouve assez illisible, mais ça ne repose sur rien de vraiment concret en terme de code.

  4. #4
    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
    Citation Envoyé par Takka Voir le message
    Malheureusement, je suis arrivé récemment, et il y a une très grosse base de code en python2, sans que j'ai de temps alloué pour tout migrer en python3
    Ouaip, tout comme le réchauffement climatique. Tous les scientifiques alertaient depuis les années 1980 mais il a fallu que des villages s'effondrent, que la grêle d'un côté et la sécheresse de l'autre ravagent les récoltent pour que tout d'un coup le gouvernement se réveille avec tout le retard qu'il faut maintenant combler.
    Et il y a d'autres exemples comme le manque de médecin alors que les stats (on sait combien on en fait chaque année) montraient que cela arriverait et quand cela arriverait. Bref plus on attend pour faire un truc inévitable plus on se prend le mur dans la tronche.

    Citation Envoyé par Takka Voir le message
    Pour ce qui est de l'utilisation de classe et non de dictionnaire, c'est plus en terme de lisibilité, avoir un gros dictionnaire avec beaucoup de données dedans est quelque chose que je trouve assez illisible, mais ça ne repose sur rien de vraiment concret en terme de code.
    Bah, rien ne t'interdit d'avoir deux dictionnaires plus courts et dédiés chacun à un domaine...
    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
    command={
    	"command1" : {
    		"mk_cmd" : "mkcomponent",
    		"rm_cmd" : "rmcomponent",
    	},
    	"command2" : {
    		"mk_cmd" : "mkothercomponent",
    		"rm_cmd" : "rmothercomponent",
    	},
    }
     
    args={
    	"args1" : {
    		"name" : "",
    		"attr1" : False,
    		"attr2" : 0,
    	},
    	"args2" : {
    		"name" : "",
    		"attr1" : True,
    		"attr2" : 1,
    	},
    }
    Après la lisibilité c'est parfois assez subjectif. Tu peux par exemple déporter ton (tes) dicos dans un module annexe que tu importes (c'est d'ailleurs ce que j'ai fait car je te décris-là exactement ma propre configuration que j'ai stockée dans un module nommé "config.py"). Ainsi quand tu ouvres ton code principal, tu n'as pas à voir le détail et si tu dois modifier le détail, tu ouvres alors le fichier spécifique mais là tu sais quoi modifier/rajouter et le truc reste lisible...

    Exemple de ma propre config (125 lignes)
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    config={
    	"bdd/connexion" : {
    		"serveur" : (str, os.environ.get("PGHOST", "/tmp")),
    		"port" : (int, os.environ.get("PGPORT", "5432")),
    		"user" : (
    			str,
    			os.environ.get(
    				"PGUSER",
    				os.environ[
    					{
    						"posix" : "LOGNAME",
    						"nt" : "USERNAME",
    					}[os.name]
    				],
    			),
    		),
    		"password" : (str, ""),
    	},
    	"parametre/appli" : {
    		"debug" : (bool, "False"),
    		"esc" : (bool, "False"),
    	},
    	"parametre/auteur" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/client" : {
    		"yearsincelastbuy" : (int, "2"),
    		"daywithoutca" : (int, "7"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/collection" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/commande" : {
    		"remiseauto" : (bool, "True"),
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/fournisseur" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/internet" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/produit" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/remise" : {
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/theme" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/vente" : {
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"affich/apparence" : {
    		"style" : (str, "Cleanlooks"),
    		"design" : (str, "default"),
    	},
    	"affich/translation" : {
    		"langage" : (str, "fr"),
    		"multilangue" : (bool, "False"),
    	},
    }
    Tu pourras remarquer une certaine similitude avec mes clefs (ex "affich/apparence") et le format des fichiers ".ini" de Windows. C'est voulu, ça me permet ainsi de prendre la config soit dans le ".ini" s'il existe, soit dans le dictionnaire écrit en dur dans le module "config.py".
    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]

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur backend (python)
    Inscrit en
    Mai 2014
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur backend (python)

    Informations forums :
    Inscription : Mai 2014
    Messages : 77
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ouaip, tout comme le réchauffement climatique. Tous les scientifiques alertaient depuis les années 1980 mais il a fallu que des villages s'effondrent, que la grêle d'un côté et la sécheresse de l'autre ravagent les récoltent pour que tout d'un coup le gouvernement se réveille avec tout le retard qu'il faut maintenant combler.
    Et il y a d'autres exemples comme le manque de médecin alors que les stats (on sait combien on en fait chaque année) montraient que cela arriverait et quand cela arriverait. Bref plus on attend pour faire un truc inévitable plus on se prend le mur dans la tronche.
    Je le sais bien, malheureusement, même en ayant essayé de faire avancer le sujet de la migration sur du python3, ce n'est pas moi qui décide du temps que je peux allouer aux différentes tâches.

    Citation Envoyé par Sve@r Voir le message
    Bah, rien ne t'interdit d'avoir deux dictionnaires plus courts et dédiés chacun à un domaine...
    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
    command={
    	"command1" : {
    		"mk_cmd" : "mkcomponent",
    		"rm_cmd" : "rmcomponent",
    	},
    	"command2" : {
    		"mk_cmd" : "mkothercomponent",
    		"rm_cmd" : "rmothercomponent",
    	},
    }
     
    args={
    	"args1" : {
    		"name" : "",
    		"attr1" : False,
    		"attr2" : 0,
    	},
    	"args2" : {
    		"name" : "",
    		"attr1" : True,
    		"attr2" : 1,
    	},
    }
    Après la lisibilité c'est parfois assez subjectif. Tu peux par exemple déporter ton (tes) dicos dans un module annexe que tu importes (c'est d'ailleurs ce que j'ai fait car je te décris-là exactement ma propre configuration que j'ai stockée dans un module nommé "config.py"). Ainsi quand tu ouvres ton code principal, tu n'as pas à voir le détail et si tu dois modifier le détail, tu ouvres alors le fichier spécifique mais là tu sais quoi modifier/rajouter et le truc reste lisible...

    Exemple de ma propre config (125 lignes)
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    config={
    	"bdd/connexion" : {
    		"serveur" : (str, os.environ.get("PGHOST", "/tmp")),
    		"port" : (int, os.environ.get("PGPORT", "5432")),
    		"user" : (
    			str,
    			os.environ.get(
    				"PGUSER",
    				os.environ[
    					{
    						"posix" : "LOGNAME",
    						"nt" : "USERNAME",
    					}[os.name]
    				],
    			),
    		),
    		"password" : (str, ""),
    	},
    	"parametre/appli" : {
    		"debug" : (bool, "False"),
    		"esc" : (bool, "False"),
    	},
    	"parametre/auteur" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/client" : {
    		"yearsincelastbuy" : (int, "2"),
    		"daywithoutca" : (int, "7"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/collection" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/commande" : {
    		"remiseauto" : (bool, "True"),
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/fournisseur" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/internet" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/produit" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/remise" : {
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/theme" : {
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"parametre/vente" : {
    		"remisemax" : (float, "20.0"),
    		"insert_confirm" : (bool, "False"),
    		"update_confirm" : (bool, "False"),
    		"delete_confirm" : (bool, "True"),
    		"insert_loop" : (bool, "True"),
    		"insert_change_id" : (bool, "True"),
    		"insert_clear" : (bool, "True"),
    	},
    	"affich/apparence" : {
    		"style" : (str, "Cleanlooks"),
    		"design" : (str, "default"),
    	},
    	"affich/translation" : {
    		"langage" : (str, "fr"),
    		"multilangue" : (bool, "False"),
    	},
    }
    Tu pourras remarquer une certaine similitude avec mes clefs (ex "affich/apparence") et le format des fichiers ".ini" de Windows. C'est voulu, ça me permet ainsi de prendre la config soit dans le ".ini" s'il existe, soit dans le dictionnaire écrit en dur dans le module "config.py".
    Et du coup, je vais partir sur le modèle avec les dictionnaires. Je pense que, à force de faire tout en objet, j'en ai oublier les bases de python.
    Merci pour les conseils

  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
    Salut,

    Citation Envoyé par Takka Voir le message
    J'ai regarder du coté des designs patterns, et le builder semble correspondre à ce que je souhaiterais faire, mais j'ai du mal à voir une bonne façon de l'implémenter
    Avec Python, il y a des "builtins" qui simplifient beaucoup le pattern standard:

    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
    class Command(object):
        def __init__(self, cmd, *args):
            self.cmd = cmd
            self.args = args
        def __call__(self, *args):
            return self.cmd(*self.args+args)
     
     
    def toto(x, y):
        print 'toto', x, y
        return x + y
     
    r = Command(toto, 1, 2)()
    print(r)
     
    r = Command(toto, 1)(4)
    print(r)
    - 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
    Citation Envoyé par wiztricks Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def toto(x, y):
        print 'toto', x, y
        return x + y
    Un petit peu contraignant: la fonction n'accepte que 2 arguments. Soit on crée l'objet avec 2 attributs, et on ne peut plus passer de paramètre lors de l'appel, soit on crée l'objet avec un seul attribut et on doit passer un second paramètre lors de l'appel. Ou alors pas d'attribut dans l'objet et deux paramètres obligatoires à l'appel...
    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
    class Command(object):
    	def __init__(self, cmd, *args):
    		self.cmd = cmd
    		self.args = args
    	def __call__(self, *args):
    		return self.cmd(*self.args+args)
     
    def toto(*args):
    	print 'toto', args
    	return sum(args)
     
    r = Command(toto, 1, 2)()
    print(r)
     
    r = Command(toto, 1, 2)(7)
    print(r)
     
    r = Command(toto, 1, 2)(7, 8)
    print(r)
     
    r = Command(toto, 1)(7, 8)
    print(r)
     
    r = Command(toto, 1)(7)
    print(r)
     
    r = Command(toto)(7)
    print(r)
     
    r = Command(toto)()
    print(r)
    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
    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 Sve@r Voir le message
    Un petit peu contraignant: la fonction n'accepte que 2 arguments. Soit on crée l'objet avec 2 attributs, et on ne peut plus passer de paramètre lors de l'appel, soit on crée l'objet avec un seul attribut et on doit passer un second paramètre lors de l'appel.
    L'idée était de montrer ce qu'on pouvait faire dans un exemple par trop compliqué qui fonctionne.
    Par exemple, j'ai eu la flemme d'ajouter des paramètres nommés...

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

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 18/12/2014, 11h10
  2. Objet unique pour différentes classes
    Par titibete dans le forum C++
    Réponses: 3
    Dernier message: 08/12/2010, 15h43
  3. Réponses: 0
    Dernier message: 06/05/2010, 17h25
  4. [XML] Génération du modèle Objet à partir d'un XSD
    Par SHizWeb dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 04/05/2010, 12h09
  5. Réponses: 2
    Dernier message: 14/09/2007, 10h18

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