"helper function" style question

R

Robert Ferrell

I have a style question. I have a class with a method, m1, which
needs a helper function, hf. I can put hf inside m1, or I can make it
another method of the class. The only place hf should ever be invoked
is from inside m1.

Is either style preferred?

Here are two short examples:

Helper function as method:

class K(object):
def _hf(self):
print 'Yo'
def m1(self):
self._hf()
return

Helper function as "private" function inside m1.

class K(object):
def m1(self):
def hf():
print 'Yo'
hf()
return

Opinions greatly appreciated.

thanks,
-robert
 
L

Larry Bates

I think it is a "personal" style question, but
I like the first example (and use it frequently).
The first method also makes it possible to
use K as a base class object, I'm unsure about
the second method (perhaps one of the class
"gurus" can chime in). I believe that in the
second example, hf() function would only be callable
in m1 method. In first example it is callable from
any method (as self._hf()) and can be called externally
as Kclassinstance._hf() (even though the leading
underline "hides" the method). If a function is
only called from inside of a single method, I question
why you would want a function at all.

HTH,
Larry Bates
Syscon, Inc.
 
P

Peter Hansen

Robert said:
I have a style question. I have a class with a method, m1, which
needs a helper function, hf. I can put hf inside m1, or I can make it
another method of the class. The only place hf should ever be invoked
is from inside m1.

Is either style preferred?

If either is, it's the first one, not the following one.
class K(object):
def m1(self):
def hf():
print 'Yo'
hf()
return

Here you are wasting time executing the "def" statement
every single time you invoke m1. I'm not sure if that
also means it is compiling it each time (I think not),
but at least it is rebinding the local hf to the function
each time through.

But I would just make hf() a function outside the class.
Since it does not reference anything inside K, it has
nothing inherently to do with K and should be outside,
possibly (eventually) to be moved to another module where
such helper functions reside to make them more maintainable.

-Peter
 
P

Paul Morrow

Your 2nd example makes the most sense from an encapsulation point of
view. If hf is only needed by m1, then it shouldn't be visible outside
of m1. Otherwise it just pollutes the namespace and makes it harder to
move m1 to a separate module/class later on down the road. I use this
technique all the time. I like to create functions, not only when I'm
going to be reusing code, but also simply when it aids the readibility
of my code. And although I'm not sure whether the 2nd technique is
slower than the first (I can imagine that the byte compiler could be
smart enough not to recompile or rebind hf on each invocation of m1), in
general, I don't worry about the performance of my code until I've got
it working correctly. And then it's usually algorithmic changes that
offer the big performance gains (not code reorganization).
 
T

Terry Reedy

Paul Morrow said:
slower than the first (I can imagine that the byte compiler could be
smart enough not to recompile or rebind hf on each invocation of m1), in
From years ago comments by those in the know, the body of inner function is
compiled just once, as for outer functions, and saved in a code object, but
the function object is recreated each time the def statement is executed.
Rebinding is necessary; so it either recreating the function object or at
least patching a cached version . Consider the following skeleton:

def outer(a, b):
if a:
def inner(x, y=b): pass
else:
def inner(x, y=): pass
return inner

Terry J. Reedy
 
P

Paul Morrow

Terry said:
slower than the first (I can imagine that the byte compiler could be
smart enough not to recompile or rebind hf on each invocation of m1), in

From years ago comments by those in the know, the body of inner function is
compiled just once, as for outer functions, and saved in a code object, but
the function object is recreated each time the def statement is executed.
Rebinding is necessary; so it either recreating the function object or at
least patching a cached version . Consider the following skeleton:

def outer(a, b):
if a:
def inner(x, y=b): pass
else:
def inner(x, y=): pass
return inner

Terry J. Reedy


But if the inner defs were not conditionally compiled (not inside of the
if stmnt --- as in the example we were considering), the compiler
*could* detect that and not have to rebind the local variable (inner)
each time. In fact, it could even inline the helper function
(eliminating the function call entirely), thereby speeding things up
even more.

But even if the Python compiler doesn't do that, I still prefer defining
things so that they are visible only within the scope where they are
needed. That generally makes program maintenance/comprehension easier,
which translates into saving 'my' time...

Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top