2009-02-01 18 views
3

J'ai créé une méthode qui génère une nouvelle classe et ajoute quelques méthodes dans la classe, mais il y a un bug étrange, et je ne sais pas ce qui se passe:Comment créer des méthodes python (signature et contenu) dans le code?

def make_image_form(image_fields): 
    ''' Takes a list of image_fields to generate images ''' 
    images = SortedDict() 
    for image_name in image_fields: 
     images[image_name] = forms.ImageField(required=False) 
    new_form = type('ListingImagesForm2', (forms.BaseForm,), {'base_fields' : images}) 
    #now we add the validation methods to the class 
    for image_name in image_fields: 
     print "image name is: ", image_name 
     setattr(new_form, 'clean_' + image_name, lambda self: self._clean_photo(image_name)) 
    #Add the _clean_photo method to the class 
    setattr(new_form, '_clean_photo', _clean_photo) 
    return new_form 

C'est ma méthode, prend une liste de champs image_fields (je crée un site dans Django), et crée tout un tas de champs ImageField, et crée une classe ListingImagesForm2, et assigne les champs d'image à la classe.

Le problème est de créer les méthodes, et plus spécifiquement le contenu de la méthode.

Dans la boucle:

for image_name in image_fields: 
    print "image name is: ", image_name 
    setattr(new_form, 'clean_' + image_name, lambda self: self._clean_photo(image_name)) 

Les signatures méthodes sont créées correctement (par exemple clean_pic_1, clean_pic_2 ...), mais je pense qu'il ya un problème dans l'expression lambda, comme la méthode _clean_photo est toujours appelé avec le même nom d'image (qui se trouve être le dernier nom d'image dans la liste image_fields).

Existe-t-il un moyen plus agréable de créer un contenu de méthode dynamique (code), que d'utiliser des expressions lambda?

Et pourquoi mon expression lambda ne passerait-elle que _clean_photo la dernière image_name dans la boucle for?

+0

Vous cherchez à corriger l'indentation du code? En python surtout, c'est très important que ce soit correct. –

+0

Si vous êtes encore en train d'apprendre Python, je vous recommande d'essayer une solution alternative ici: les choses peuvent devenir confuses avec la création de classe dynamique, comme vous avez trouvé! Que diriez-vous de définir une classe générique ailleurs et de personnaliser ses attributs en fonction des images? Pas exactement ce que vous avez maintenant, mais proche .. –

Répondre

4

Le code Python se comporte comme ceci pour les fonctions définies dans la portée des méthodes. Utilisez cette place:

for image_name in image_fields: 
    print "image name is: ", image_name 
    setattr(new_form, 'clean_' + image_name, 
      lambda self, iname=image_name: self._clean_photo(iname)) 

L'utilisation de l'argument de mot-clé par défaut fait Python se rappeler au moment de la création de la fonction lambda plutôt que au moment de son appel (quand il serait toujours prendre la dernière image).