Функция Python со слишком многими аргументами со значениями по умолчанию, как сделать это чище? - PullRequest
2 голосов
/ 01 ноября 2010

У меня есть следующая сигнатура функции, и она выглядит ужасно, что я могу сделать, чтобы она выглядела чище?

def contact(
  request, sender=settings.DEFAULT_FROM_EMAIL,
  subj_tmpl='contato/subject.txt',msg_tmpl='contato/msg.html',
  template='contato/contato.html', success_template='contato/success.html',
  success_redir='/',append_message=None,):

Ответы [ 5 ]

4 голосов
/ 01 ноября 2010

если бы я был тобой, я думаю, я сделаю это так:

def contact(request, sender=None, append_message=None, context=None):

   if not sender:
       sender = settings.DEFAULT_FROM_EMAIL  # i hope that you can access settings here

   # The context arg is a dictionary where you can put all the others argument and 
   # you can use it like so :

   subj_tmpl = context.get('subj_tmpl', 'contato/subject.txt')
   # ....

надеюсь, это тебе поможет.

3 голосов
/ 01 ноября 2010

Мое предложение - сбросить параметры.Вы действительно должны быть в состоянии указать все шаблоны отдельно?Разве не достаточно просто указать папку с шаблоном, а затем указать, что в ней есть subject.txt, msg.html и т. Д.?

Если вы хотите улучшить читабельность, переформатируйте ее, чтобы онапараметр на строку:

def contact(
  request, 
  sender=settings.DEFAULT_FROM_EMAIL,
  subj_tmpl='contato/subject.txt',
  msg_tmpl='contato/msg.html',
  template='contato/contato.html', 
  success_template='contato/success.html',
  success_redir='/',
  append_message=None,):

Это позволит читателю быстрее понять, как называются параметры.

0 голосов
/ 01 ноября 2010

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

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

что-то вроде этого:

class ContactForm(object):
    def __init__( self, 
                  subj_tmpl='contato/subject.txt',
                  msg_tmpl='contato/msg.html',
                  template='contato/contato.html',  
                  success_template='contato/success.html',
                  success_redir='/',
                  append_message=None):
        self.subj_tmpl = subj_tmpl
        self.msg_tmpl = msg_tmpl
        self.template = template
        self.success_template = success_template
        self.success_redir = success_redir
        self.append_message = append_message

    def __call__( self, request, sender=settings.DEFAULT_FROM_EMAIL ):
        # do something

# use case:
contact = ContactForm()
contact( req, sndr )

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

0 голосов
/ 01 ноября 2010
def contact(request, **kwargs):
    sender = kwargs.get('sender', settings.DEFAULT_FROM_EMAIL)
    subj_template = kwargs.get('subj_template', 'contato/subject.txt')
    ..

С учетом сказанного, я думаю, что ваше текущее решение лучше, чем использование **kwargs.

0 голосов
/ 01 ноября 2010

Вы можете переписать его как:

def contact( request, **kargs):
    try:
        sender = kwargs.pop ('sender')
    except KeyError:
        sender=settings.DEFAULT_FROM_EMAIL

    try:
        subj_tmpl = kwargs.pop ('subj_tmpl')
    except KeyError:
        subj_tmpl='contato/subject.txt'

    # ... 
    # and so on 
    # ...
...