Bonsoir.

J'essaie de faire un truc qui dépasse mes compétences.

Je mets à jour un module interne à ma boite, module servant à définir un type d'objet (un propulseur en l’occurrence). Pour le moment ce module implémente une unique classe. Quelque soit le type de propulseur il est créé par cette classe qui implémente de nombreuses méthodes. La classe est bourrée de conditions car certains propulseurs ont des attributs que d'autres non pas, de même pour les méthodes. Bref c'est le bor**l. Je m'efforce de rationaliser tout ça en créant plusieurs classes, une classe par type de propulseur.

L'idée est la suivante:
  • Une base class définissant les attributs et méthodes communes à tout type de propulseur
  • Plusieurs classes héritant de la base class avec des paramètres/attributs et méthodes particulieres
  • Une factory (fonction) permettant de faire l'interface entre les nouvelles classes et le reste du code plus ancien


Voici le code. J'ai essayé de simplifier au max, sans grand succès:
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
# -*- coding: utf-8 -*-
 
class BaseThruster(object):
    def __init__(self, name, value, option=None):
        self.name = name
        self.value = value
        self.option = option
 
    def __str__(self):
        return str(self.name) + ' of type ' + self.__class__.__name__
 
class ThrusterA(BaseThruster):
    def __init__(self, special_arg=None, *args, **kwargs):
        BaseThruster.__init__(self, *args, **kwargs)
        self.special_arg = special_arg
 
class ThrusterB(BaseThruster):
    def __init__(self, special_arg=None, other_arg= None, *args, **kwargs):
        BaseThruster.__init__(self, *args, **kwargs)
        self.special_arg = special_arg
        self.other_arg = other_arg
 
def factory(*args, **kwargs):
    kws = kwargs.copy()
    special_arg = kws.pop('special_arg', None)
    other_arg = kws.pop('other_arg', None)
    if kwargs['value'] == 1:
        return ThrusterA(special_arg, **kws)
    elif kwargs['value'] == 2:
        return ThrusterB(special_arg, other_arg, **kws)
    else:
        raise ArgumentError('Some text')
 
 
if __name__ == '__main__':
 
    obj_params_1 = {'name': '1', 'value': 1, 'special_arg': 'foo'}
    obj_params_2 = {'name': '2', 'value': 2, 'special_arg': 'foo', 'other_arg': 'bar'}
 
    obj_1 = factory(**obj_params_1)
    obj_2 = factory(**obj_params_2)
    # Don't work as expected:
    obj_3 = factory('toto',  1, arg3=None, other_arg='tata')
 
    print obj_1
Le problème c'est que je trouve tout cela bancal. Ceci par exemple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
def __init__(self, special_arg=None, *args, **kwargs)
Est-ce correct de placer une argument par défaut avant le reste des arguments? Je ne crois pas. Mais je ne parviens pas à faire sans.
Et je ne peux plus créer mes objets sans unpacker depuis un dico:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
obj_3 = factory('toto',  1, arg3=None, other_arg='tata')
Est-ce que vous avez des conseils sur la bonne pratique? Un lien peut-être vers un tuto ou quelque chose expliquant cela?

Merci par avance.

J