2012-03-02 5 views
0

J'ai une carte qui dit mappe une chaîne à une fonction comme:Envoi pointeur de fonction avec des arguments avec, puis ajouter des arguments supplémentaires en invoquant

validator = {'first_name' : validate_str, 
      'last_name' : validate_str, 
      'phone' : validate_phone } 

Je dois appeler la fonction de validation correspondante en fonction du type de la valeur que j'ai dans la carte qui sera nourri à moi comme entrée pour par exemple

for name in elements: 
    # Validate the value of this name in the input map using the function 
    # input is the map that has the value for each of these fields 
    # elements is a list of all fields used to loop through one input at a time 
    if validator[name](input[name]) is False: 
     # Throw validation error 
    else: 
     # Do something else 

Cela fonctionne bien, sauf pour ce scénario, je ne sais pas si cela peut être fait:

Le validate_str vérifie également si une chaîne est de longueur désirée max.

def validate_str(str, max-len): 
    # Throw error if len(str) > max-len 

Le max-len peut varier en fonction de la chaîne, donc je dois appeler validate_str pour prenom avec 64 caractères et dire nom avec 256 caractères.

Je peux utiliser une autre carte pour dire que ce champ a ce max_len, mais est-il possible que la carte de validateur ait un pointeur vers la fonction validate_str avec l'argument max-len basé sur le champ?

quelque chose comme:

validator = {'first_name' : validate_str(max-len=64), 
      'last_name' : validate_str(max-len=256), 
      'phone' : validate_phone } 

puis l'appeler pour la validation comme:

if validator[name](str=input[name]) is False: 
    # The appropriate value for max-len goes with the function call and just the 
    # str is appended to the argument list while invoking. 

Cela rend la vie plus facile pour que nous ne devons pas alors souvenez-vous encore quels champs auront le max-len envoyé le long avec ça.

+0

fautes de frappe possibles: Par 'validate' voulez-vous dire' validator'? Qu'est-ce que les 'elements'? Il semble être une liste de chaînes comme 'first_name',' last_name', ou un dictionnaire. – ninjagecko

+0

Corrigé les erreurs .. Merci de le signaler .. –

+0

Pas de problème. Vous pourriez gagner en faisant 'elements' un dictionnaire' data = {'first_name': 'Bob', 'last_name': 'Bobley', 'phone': 1234567890} 'et en faisant' field, valeur dans data.items() : sinon validateur [champ] (valeur): ... '. Lit beaucoup plus proprement. – ninjagecko

Répondre

3

Vous pouvez utiliser lambda pour créer une fonction d'un argument (la chaîne en cours de validation), mais a la longueur définie dans dans:

{'first-name':lambda x: validate-str(x, 64), ... 
+0

Fonctionne comme un champion .. Bravo à vous :-) –

+2

C'est l'une des deux réponses que le PO recherchait. Pour référence, ceci utilise un lambda pour afficher une fonction. – ninjagecko

0

Il y a deux façons de le faire.

La réponse que vous avez spécifiquement demandée est de savoir comment l'exécuter (ce que Scott Hunter a répondu).

Une autre façon est d'utiliser pour retourner une fonction qui capture les paramètres personnalisés dans une fermeture, comme une usine de fonction (« fonction d'ordre supérieur »):

def makeStringValidator(maxLength=64): 
    def validator(string): 
     return len(string)<maxLength 
    return validator 

En général, cependant, vous restreindre à ce système vous empêche d'avoir une validation "transversale" entre les champs. Par exemple, si les champs birthday_day, birthday_month, birthday_year étaient séparés, vous pouviez vérifier individuellement que chaque jour correspondait à 30 ou 31, mais que vous ne connaissiez pas le mois afin de déterminer lequel (également les jours intercalaires en février). Cependant, j'utilise personnellement ce système de temps en temps. Vous pouvez simplement compléter votre système actuel avec quelque chose de plus compliqué plus tard, si de tels besoins se présentent.

+0

Merci! Cela fonctionne bien aussi .. :-) –

Questions connexes