Using closures and partial functions to eliminate redundant code
timaranz at gmail.com
timaranz at gmail.com
Wed Sep 26 23:16:56 EDT 2007
On Sep 27, 2:01 pm, Matthew Wilson <m... at tplus1.com> wrote:
> I wrote some code to create a user and update a user on a remote box by
> sending emails to that remote box. When I was done, I realized that my
> create_user function and my update_user function were effectively
> identical except for different docstrings and a single different value
> inside:
>
> ### VERSION ONE
>
> def create_user(username, userpassword, useremail):
> "Send an email that will create a user in the remote system."
>
> # Build email
> email_body = """
> USERNAME = %s
> USERPASSWORD = %s
> USEREMAIL = %s
> """ % (username, userpassword, useremail)
>
> # send it.
> send_email(subject="CREATE", body=email_body)
>
> def update_user(username, userpassword, useremail):
> "Send an email that will update a user's password in the remote system."
>
> # Build email
> email_body = """
> USERNAME = %s
> USERPASSWORD = %s
> USEREMAIL = %s
> """ % (username, userpassword, useremail)
>
> # send it.
> send_email(subject="UPDATE", body=email_body)
>
> ### END
>
> Then I came up with this approach to avoid all that redundant text:
>
> ### VERSION TWO
>
> def _f(mode):
>
> if mode not in ("create", "update"):
> raise ValueError("mode must be create or update!")
>
> def _g(username, userpassword, useremail):
>
> # Build email
> email_body = """
> USERNAME = %s
> USERPASSWORD = %s
> USEREMAIL = %s
> """ % (username, userpassword, useremail)
>
> # send it.
> send_email(subject=mode.upper(), body=email_body)
>
> # Seems goofy, but other ways are there?
>
> docstrings = {'create': "Send an email that will create a user in the remote system.",
> 'update': "Send an email that will update a user's password in the remote system."}
>
> _g.__doc__ = docstrings[mode]
>
> return _g
>
> # Then I created my functions like this:
>
> v2_create_user = _f("create")
> v2_update_user = _f("update")
>
> ### END
>
> Finally, I came up with this approach:
>
> ### VERSION THREE
>
> from functools import partial
>
> def _h(mode, username, userpassword, useremail):
>
> if mode not in ("create", "update"):
> raise ValueError("mode must be create or update!")
>
> # Build email
> email_body = """
> USERNAME = %s
> USERPASSWORD = %s
> USEREMAIL = %s
> """ % (username, userpassword, useremail)
>
> # send it.
> send_email(subject=mode.upper(), body=email_body)
>
> # I can't figure out how to set up the docstring on these.
>
> v3_create_user = partial(_h, mode="create")
> v3_update_user = partial(_h, mode="update")
>
> ### END
>
> I'm interested to hear how other people deal with really similar code.
> The similarity just bugs me. However, I wonder if using stuff like
> closures or partial function application is needlessly showy.
>
> Also, I hope anyone here can help me figure out how to attach a
> meaningful docstring for my version three code.
>
> Thanks in advance!
>
> Matt
Without using partials, I would do something like
def _create_or_update_user(mode, username, userpassword, useremail)
blah, blah, blah
def update_user(username, userpassword, useremail):
'update doc string'
return _create_or_update_user('update', username, userpassword,
useremail)
def create_user(username, userpassword, useremail):
'create doc string'
return _create_or_update_user('create', username, userpassword,
useremail)
Cheers
Tim
More information about the Python-list
mailing list