Как вы создаете методы Python (подпись и контент) в коде? - PullRequest
3 голосов
/ 01 февраля 2009

Я создал метод, который генерирует новый класс и добавляет некоторые методы в класс, но есть странная ошибка, и я не уверен, что происходит:

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

Это мой метод, который берет список полей image_fields (я делаю сайт в Django), и он создает целую кучу полей ImageField, создает класс ListingImagesForm2 и назначает поля изображения этому классу.

Проблема заключается в создании методов и, в частности, содержания метода.

В цикле:

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))

Сигнатуры методов созданы правильно (например, clean_pic_1, clean_pic_2 ...), но я думаю, что есть проблема в лямбда-выражении, поскольку метод _clean_photo всегда вызывается с тем же именем изображения (которое оказывается последним имя изображения в списке полей image_fields).

Есть ли более приятный способ создания содержимого (кода) динамического метода, чем использование лямбда-выражений?

И почему мое лямбда-выражение передает только _clean_photo последнее имя_изображения в цикле for?

1 Ответ

4 голосов
/ 01 февраля 2009

Код Python ведет себя так же для функций, определенных в области методов. Используйте это вместо:

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))

Использование аргумента ключевого слова по умолчанию заставляет Python запоминать его во время создания лямбда-функции, а не во время ее вызова (когда он всегда берет последнее изображение).

...