Using closures and partial functions to eliminate redundant code
Bruno Desthuilliers
bruno.42.desthuilliers at wtf.websiteburo.oops.com
Thu Sep 27 03:30:34 EDT 2007
Matthew Wilson a écrit :
> 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
(snip)
>
> 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.
Depends.
> The similarity just bugs me. However, I wonder if using stuff like
> closures or partial function application is needlessly showy.
Not necessarily, but in this case, it's just overkill IMHO - I'd just
have factored out the common code:
def _build_email(username, userpassword, useremail):
""" builds the email body used by create_uer and update_user """
return """
USERNAME = %s
USERPASSWORD = %s
USEREMAIL = %s
""" % (username, userpassword, useremail)
def create_user(username, userpassword, useremail):
"Send an email that will create a user in the remote system."
send_email(subject="CREATE",
body=_build_email(username, userpassword, useremail)
)
def update_user(username, userpassword, useremail):
"Send an email that will update a user's password in the remote
system."
send_email(subject="UPDATE",
body=_build_email(username, userpassword, useremail)
)
Now there are of course cases where either closures and/or partials are
the right thing to do.
> Also, I hope anyone here can help me figure out how to attach a
> meaningful docstring for my version three code.
Didn't try, but what about:
p = partial(func, arg)
p.__doc__ = "yadda yadda"
More information about the Python-list
mailing list