helper function in a class' namespace

H

Helmut Jarausch

Hi,

the following code works fine

def Helper(M) :
return 'H>'+M

class A(object):
def __init__(self,Msg) :
print Helper(Msg)

B=A('ZZ')

but the Helper function is in the module's namespace.

I'd like to put it into class A's namespace.
Note, the Helper function doesn't need access to any instance attributes.

The first variant

class A(object):
def Helper(M) :
return 'H>'+M
def __init__(self,Msg) :
print Helper(Msg)

doesn't work since Python is looking for a global function Helper (why?)

The alternative

class A(object):
def Helper(M) :
return 'H>'+M
def __init__(self,Msg) :
print A.Helper(Msg)

doesn't work either since now the first argument to A.Helper must be 'A'.

So, isn't it possible to have a helper function in the namespace of a class
without (the overhead of) passing a 'self' or a 'cls' parameter?

Probably I'm hurt by my C++ history.

Many thanks for your help,
Helmut.



--
Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany
 
S

Stargaming

Hi,

the following code works fine

def Helper(M) :
return 'H>'+M

String concatenation is generally considered unpythonic, better use
string interpolation::

'H> %s' % (M,)
class A(object):
def __init__(self,Msg) :
print Helper(Msg)

B=A('ZZ')

Watch out your names -- they could confuse other Python programmers
introspecting your namespaces! Names bound to objects should generally be
lowercase (argument ``msg``, object ``b``, argument ``m``, function
``helper``). For details on what the Python community has agreed on is
"good style," see the `Style Guide <http://www.python.org/dev/peps/
pep-0008/>`_.
but the Helper function is in the module's namespace.

Where's the problem? If it is "I don't want Helper to be visible", just
use this convention: "Names beginning with an underscore are private.
Better keep your fingers off."
I'd like to put it into class A's namespace. Note, the Helper function
doesn't need access to any instance attributes.

The first variant

class A(object):
def Helper(M) :
return 'H>'+M
def __init__(self,Msg) :
print Helper(Msg)

doesn't work since Python is looking for a global function Helper (why?)

Because in the scope of the ``__init__`` function, the name ``Helper`` is
not bound. It then jumps out to the global scope.
The alternative

class A(object):
def Helper(M) :
return 'H>'+M
def __init__(self,Msg) :
print A.Helper(Msg)

doesn't work either since now the first argument to A.Helper must be
'A'.

So, isn't it possible to have a helper function in the namespace of a
class without (the overhead of) passing a 'self' or a 'cls' parameter?

Of course it is! You can decorate certain functions with the
`staticmethod <http://docs.python.org/lib/built-in-funcs.html#l2h-69>`_
wrapper, which will do exactly what you wanted::

class A(object):
@staticmethod
def helper(m):
return 'H>%s' % (m,)
def __init__(self, msg):
print A.helper(msg) # or self.helper


HTH,
 
S

Steven D'Aprano

String concatenation is generally considered unpythonic, better use
string interpolation::

'H> %s' % (M,)

String concatenation is significantly faster than string interpolation.
import timeit
timeit.Timer("'H> %s' % M", "M = 'abcdef'").repeat() [1.3407769203186035, 0.69128704071044922, 0.56362509727478027]
timeit.Timer("'H> ' + M", "M = 'abcdef'").repeat()
[0.69647812843322754, 0.69620108604431152, 0.65643787384033203]

The danger with string concatenation comes from building up a string
piece by piece: even though a single + is faster than a single %, a dozen
concats will likely be MUCH slower than a single &.

Also, the tuple above is totally unnecessary. 'H> %s' % M will work fine.
 
A

Arnaud Delobelle

String concatenation is generally considered unpythonic, better use
string interpolation::
    'H> %s' % (M,)
[...]
Also, the tuple above is totally unnecessary. 'H> %s' % M will work fine.

...except if M is a tuple:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting


Pedantically yours,
 
A

Arnaud Delobelle

Because in the scope of the ``__init__`` function, the name ``Helper`` is
not bound. It then jumps out to the global scope.

But it is 'Helper' bound in the scope of the *definition* of __init__,
hence you *could* write:
... def _helper(x): return '<<%s>>' % x
... def __init__(self, msg, _helper=_helper):
... print _helper(msg)
... del _helper
...<<spam>>
<__main__.A object at 0x70170>

Confusingly yours,
 

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

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top