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