Допустимо ли использовать ** kwargs и декоратор для предотвращения повторения кода? - PullRequest
3 голосов
/ 28 октября 2011

В настоящее время я пишу библиотеку API на Python, и мне интересно, является ли следующий код слишком непифоничным:

@accepts('video_id', 'reference_id', 'page_size', 'page_number',
         'get_item_count', 'fields', 'video_fields', 'custom_fields',
         'media_delivery', 'output')
@requires('video_id', 'reference_id')
def find_related_videos(self, **params):
    return ItemCollection(read_request(params))

Декоратор accepts выдает ошибку, если в kwargs нетсписок передается методу.Он также выполняет проверку для определенных ключевых слов.

Декоратор requires обеспечивает наличие этих аргументов ключевых слов.

Отсутствие аргументов ключевого слова в определении метода вызывает у меня проблемы.Однако необходимость составления словаря параметров вручную для каждого метода также выглядит раздражающей.Кроме того, существует проверочный код, который одинаков для каждого экземпляра аргумента video_fields, передаваемого методу, поэтому я могу вызвать его из декоратора accept, чтобы избежать повторения.

Мысли?

Ответы [ 4 ]

1 голос
/ 28 октября 2011

Как насчет этого решения?

def check_params(params):
    # Do whatever check you want to do on params
    return dict((k, v) for k, v in params
                if v is not None and k != "self")

def find_related_videos(self, video_id, reference_id, page_size=None,
                        page_number=None, get_item_count=None, fields=None,
                        video_fields=None, custom_fields=None,
                        media_delivery=None, output=None):
    params = check_prams(locals())
    return ItemCollection(read_request(params))

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

1 голос
/ 28 октября 2011

Я бы обязательно поставил обязательные поля в сигнатуре метода:

def find_related_videos(self, video_id, reference_id, **params):
    params.update({'video_id': video_id, 'reference_id': reference_id})
    return ItemCollection(read_request(params))

Если возможно, я бы даже изменил read_request, чтобы он также принимал ключевые аргументы:

def find_related_videos(self, video_id, reference_id, **params):
    return ItemCollection(read_request(video_id=video_id, reference_id=reference_id, **params))

Что касается допустимых параметров, лично я не буду выдавать ошибки за недействительные параметры - я просто игнорирую те, которые мне не нужны.

0 голосов
/ 28 октября 2011

Если вы сделаете это:

def find_related_videos(self, video_id, reference_id, ...)

, тогда вы все равно можете использовать декоратор для проверки правильности аргументов и оставить интерпретатор для принудительного применения остальных.Однако есть некоторые компромиссы.

  • Используя позиционные аргументы, вы больше не позволяете вызывающей стороне указывать аргументы в любом порядке.Если вы в основном читаете в словаре и пропускаете его или что-то в этом роде, это может быть проблемой.
  • Труднее написать ваш @accepts (или @validate) декоратор, чтобы проверить правильностьаргументы в том же общем смысле.Это все еще можно сделать с помощью функции inspect.getargspec, и раньше я делал нечто подобное, но вам понадобится некоторое время, чтобы это заработало.Мой декоратор для автоматического сопоставления параметров HTTP GET с аргументами функции сложен, но работает.
0 голосов
/ 28 октября 2011

Я бы сделал это без декораторов. Читателям гораздо проще следовать по пути выполнения кодов без декораторов:

required = set(['video_id', 'reference_id'])
acceptable = required.union(set(['page_size', 'page_number', 'get_item_count', 'fields', 'video_fields', 'custom_fields', 'media_delivery', 'output']))

def find_related_videos(self, **params): 
    if not (required.issubset(set(params.keys())) or set(params.keys()).issubset(acceptable)):
        raise Exception("Some exception")
    return ItemCollection(read_request(params))

Это позволит проверить, все ли ключи kwargs входят в набор acceptable и имеют ли они хотя бы required аргументов.

...