2017-06-30 1 views
0

J'ai une fonction/méthode A() qui attend quelques arguments (y compris les arguments optionnels). Une autre fonction B() effectue le pré-traitement sur les données à transmettre à ladite fonction A(). J'ai peu de mise en œuvre alternative de la fonction B() qui me cause la confusion quant aux avantages de l'un sur l'autre. Je voudrais savoir lequel d'entre eux (le cas échéant) devrais-je utiliser.Comment passer des arguments à une fonction en utilisant Python (dict vs variables)?

Après tout, There should be one-- and preferably only one --obvious way to do it.

Voici l'extrait de code:

class Foo(object): 

    def __init__(self, param1, param2, param3=None): 
     self.param1 = param1 
     self.param2 = param2 
     self.param3 = param3 

    @classmethod 
    def from_dump_v1(cls, dump): 
     param1, param2, param3 = dump.get('param_1'), dump.get('_param_2'), dump.get('paramThree') 
     return cls(param1, param2, param3) 

    @classmethod 
    def from_dump_v2(cls, dump): 
     dump['param1'] = dump.pop('param_1') 
     dump['param2'] = dump.pop('_param_2') 
     dump['param3'] = dump.pop('paramThree') 
     return cls(**dump) 

    @classmethod 
    def from_dump_v3(cls, dump): 
     result = dict() 
     result['param1'] = dump.get('param_1') 
     result['param2'] = dump.get('_param_2') 
     result['param3'] = dump.get('paramThree') 
     return cls(**result) 

Dans le code ci-dessus, __init__ fait référence à A() et from_dump_v* représentent les différentes implémentations que je dois choisir.
NOTE: Dans tous les cas, le dump est un dictionnaire avec 3 paires de valeurs-clés, à savoir param_1, _param_2 et paramThree.

+0

Désolé pour plus de simplifier ma question ici. J'ai mis à jour la question avec des exigences plus réalistes. –

Répondre

7

Une façon évidente faire cela pourrait être:

@classmethod 
def from_dump_v(cls, dump): 
    return cls(**{k.replace('_', ''): v for k, v in dump.items()}) 

Dans le cas du dump dict contient des clés arbitraires, je ne vois pas la d'une façon évidente de le faire; Je ne suis pas néerlandais.

Cependant, avec un certain contrôle sur l'argument de la fonction d'usine, vous pouvez modifier le type de données à une séquence au lieu d'un dict, puis faire quelque chose d'évident avec enumerate:

@classmethod 
def from_dump_v(cls, dump): 
    return cls(**{"param{}".format(i): x for i, x in enumerate(dump, 1)}) 
+0

Mais je ne souhaite pas toujours remplacer "_". –

+0

@KshitijSaraogi Eh bien, vous pouvez écrire une fonction pour transformer la clé de la manière dont vous avez besoin et l'utiliser dans la compréhension du dictionnaire. Ou vous pourriez développer votre exemple afin que nous puissions examiner et aborder les autres possibilités. –

0

Il semble que vous font une fonction d'usine pour gérer votre initialisation de classe. Donc, pour que cela se produise, vous pouvez utiliser *args et **kwargs pour transmettre n'importe quel nombre d'arguments (paramètres et arguments) à votre fonction d'usine. Mais cela semble redondant.

Par conséquent, vous pouvez avoir quelque chose comme ceci:

class Foo(object): 
    def __init__(self, param1, param2, param3=None): 
     self.param1 = param1 
     self.param2 = param2 
     self.param3 = param3 

    @classmethod 
    def from_dump_vx(cls, *args, **kwargs): 
     return cls(*args, **kwargs) 

En from_dump_vx, vous pouvez traiter les valeurs *args et **kwargs à votre préférence et puis les passer à la méthode __init__ de votre classe.

Ensuite, vous pouvez initialiser votre classe comme ceci:

y = Foo.from_dump_vx(1, 2, param3=3)