473,233 Members | 1,596 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,233 software developers and data experts.

Using closures and partial functions to eliminate redundant code

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
Sep 27 '07 #1
5 1561
On Sep 26, 9:01 pm, Matthew Wilson <m...@tplus1.comwrote:
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
Haven't used partial yet, but I'm very interested. Of course, I think
this will work just as well:

def make_method(mode,docstring):
def _inner(username, userpassword, useremail):
# implementation of common routine code goes here
# note: no need to clutter arg list with 'mode' now
_inner.__name__ = mode + "_user"
_inner.__doc__ = docstring
return _inner

Does this not work?

v3_create_user = partial(_h, mode="create")
v3_create_user.__doc__ = "Send an email that will create a user in
the remote system."
v3_update_user = partial(_h, mode="update")
v3_update_user.__doc__ = "Send an email that will update a user's
password in the remote system."
-- Paul

Sep 27 '07 #2
On Sep 27, 2:01 pm, Matthew Wilson <m...@tplus1.comwrote:
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

Sep 27 '07 #3
En Wed, 26 Sep 2007 23:01:17 -0300, Matthew Wilson <ma**@tplus1.com>
escribi�:
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:
I would have used an object with two methods... But this is just another
example of the closure/object dichotomy. Some enlightment:
http://people.csail.mit.edu/gregs/ll.../msg03277.html

--
Gabriel Genellina

Sep 27 '07 #4
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"

Sep 27 '07 #5
Matthew Wilson wrote:
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.
ACK -- but not because it's showy, but because it may be more
error-prone and less readable. I'd often use an approach like this:

def create_user(username, userpassword, useremail, create = False):
"""
Send an email that will update a user in the remote system.
If create evaluates to True, don't update the user, but create
her instead.
"""
if not create:
subject = "UPDATE"
else:
subject = "CREATE"

# Build email
email_body = """
USERNAME = %s
USERPASSWORD = %s
USEREMAIL = %s
""" % (username, userpassword, useremail)
# send it.
send_email(subject=subject, body=email_body)

Regards,
Björn

--
BOFH excuse #353:

Second-system effect.

Sep 27 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: paolo veronelli | last post by:
I've a vague idea of the differences,I don't know scheme anyway. I'd like to see an example to show what is missing in python about closures and possibly understand if ruby is better in this...
28
by: Daniel | last post by:
Hello =) I have an object which contains a method that should execute every x ms. I can use setInterval inside the object construct like this - self.setInterval('ObjectName.methodName()',...
6
by: Joe Kelsey | last post by:
When you use addEventListener (or addEvent in IE) to call an object method, does it call it with the correct this parameter? The ECMAScript reference has a lot to say about the caller using...
21
by: Rubén Campos | last post by:
I haven't found any previous message related to what I'm going to ask here, but accept my anticipated excuses if I'm wrong. I want to ask about the real usefulness of the 'inline' keyword. I've...
6
by: marktm | last post by:
Hi- I am trying to use setInterval to call a method within an object and have not had any luck. I get "Object doesn't support this property or method" when I execute the following code. What I...
19
by: Paul | last post by:
hi, there, for example, char *mystr="##this is##a examp#le"; I want to replace all the "##" in mystr with "****". How can I do this? I checked all the string functions in C, but did not...
5
by: Bern McCarty | last post by:
I have a DLL written in C++ (it's really C code that was adjusted to compile OK as C++) that I compile successfully into IL with the /CLR switch of Visual C 7.1. I use the resultant library...
2
by: Jake Barnes | last post by:
Using javascript closures to create singletons to ensure the survival of a reference to an HTML block when removeChild() may remove the last reference to the block and thus destory the block is...
10
by: Emre Sevinc | last post by:
Take a look at the following snippet: <html> <head> <script> function add(elementId) { var container = document.getElementById(elementId); for (var i = 0; i < 10; i++) { var elt =...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.