utility functions within a class?

J

John Salerno

I might be missing something obvious here, but I decided to experiment
with writing a program that involves a class, so I'm somewhat new to
this in Python.

Anyway, what is the best way to create a function (A) within a class
that another function (B) can use? Function A is not something that an
instance will ever call, so I figure it's a choice between static or
class methods, but I don't know which one, or if this is even the right
approach.

Specifically, I am writing a class that defines methods that wrap string
arguments inside HTML elements, and ultimately creates and HTML page. I
know there are probably a ton of programs like this already, but this is
just to give me something to do with Python.

So I have a generate() method that will create the final HTML file once
you are done creating elements. First it will create a string with the
proper DTD, then it will append the <head> element and the <body>
element, wrapped in the <html> element.

Rather than have the generate() function do all the work, I thought I
could write two utility functions to generate the head and body
elements. These would simply wrap the element names around some
pre-defined text (for the head) and around all the other elements (for
the body).

So I'm wondering, how would I define these two functions? They would be
called from the generate method solely for the purpose of creating the
head and body blocks.

Thanks!
 
B

blair.bethwaite

It sounds like all you want is some encapsulation, the following makes
methods __head__ and __body__ "private" - the double underscores are
important. I'd suggest reading the Object bits of the python tutorial
also.

class HTMLWrapper:

def generate(self, ...):
...
self.__head__(foo)
...
self.__body__(bar)
...

def __head__(self, ...):
...

def __body__(self, ...):
...
 
J

jeffshannon

You do *NOT* want to put double-underscores before and after a method
name. That does not indicate a private method, it indicates a "magic
method" -- something that has special meaning to Python. Thus, you
have special methods like __init__(), __len__(), __getattr__(),
__setattr__(), etc; all of these methods may be called *by Python* in
certain specific circumstances, and allow you to customize how your
objects respond to those circumstances.

Naming methods that are *not* special "magic methods" using this naming
convention is a very bad idea.

On the other hand, methods with only a single or double *leading*
underscore, and no trailing underscore(s), can be considered to express
some degree of privacy. A single underscore, by convention, indicates
an internal method or attribute, and that name will typically not be
exported. A double underscore will trigger minimal name mangling; not
only will the name not be exported, but it will be converted to
_<classname>__<name>, making it a bit more difficult to access from
outside the class. (Access inside the class is via the unmangled
name.)

In this circumstance, I'd probably have methods _generate_head(self)
and _generate_body(self). Don't mess with making them class/static
methods unless it's important to be able to access them when you don't
have any instance of the class available (and if you're calling them
from inside a regular method, then you *do* have an instance
available). Even if you don't end up referring to self or any instance
attributes within the method, it's simpler to keep it as a normal
method.

--Jeff Shannon
 
B

blair.bethwaite

You do *NOT* want to put double-underscores before and after a method
name. That does not indicate a private method, it indicates a "magic
method"

WHOOPS!!

Sorry, I haven't touched python for a few months and just started
working on a script this morning so was going to post my own question
when I got sidetracked answering this thread. I guess that might be a
good reason not to use underscores as significant syntax.

Cheers,
-B
 
J

John Salerno

Even if you don't end up referring to self or any instance
attributes within the method, it's simpler to keep it as a normal
method.

Thanks, that makes sense to me! So basically just create them as
methods, and if I want a little 'privacy' I can lead with an underscore?
Somehow that sounds like the right idea... :)
 
J

John Salerno

Even if you don't end up referring to self or any instance
attributes within the method

Hmm, follow-up: I *do* plan to refer to instance attributes inside these
methods (self.something), but does that require that they be instance
methods, or can they still reference 'self' since they are inside the class?

They won't be called directly from an instance, which is why I wondered
about making them static or class methods, but can static or class
methods use self, or does it have to be an instance method in that case?
 
J

John Salerno

John said:
Hmm, follow-up: I *do* plan to refer to instance attributes inside these
methods (self.something), but does that require that they be instance
methods, or can they still reference 'self' since they are inside the class?

They won't be called directly from an instance, which is why I wondered
about making them static or class methods, but can static or class
methods use self, or does it have to be an instance method in that case?

Ugh, sorry about another post, but let me clarify: In these utility
functions, I need to refer to an attribute of an instance, but these
functions will be called from another method in the class, not from the
instance itself. Is this even possible, or would 'self' have no meaning
when used this way?
 
B

blair.bethwaite

John said:
Ugh, sorry about another post, but let me clarify: In these utility
functions, I need to refer to an attribute of an instance, but these
functions will be called from another method in the class, not from the
instance itself. Is this even possible, or would 'self' have no meaning
when used this way?

I'm having trouble deciphering what this bit means - "but these
functions will be called from another method in the class, not from the
instance itself", I don't think it makes sense.

If you're calling something in a class method then there must be an
instance of that class, instantiated as an object, in order to make the
call in the first place.

'self' does have meaning inside a class, you use it when you want to
call another method within the same class. Python can then fill in the
self reference in the arguments to the callee for you as it does when
you call a method from outside of the class by qualifying with the
instance name.
inside class A:
self.blah(args)
outside class A:
a_A = A()
a_A.blah(args)

Cheers,
-B
(Hope I've got this one right)
 
J

John Salerno

I'm having trouble deciphering what this bit means - "but these
functions will be called from another method in the class, not from the
instance itself", I don't think it makes sense.

Yeah, I'm starting to see that as I tried to implement it. Here's what I
came up with, which works:

def generate(self, filename):
self.head = self.generate_head()
self.body = self.generate_body()

So the two generate_* methods are called from within another class
method, and it seemed necessary to still call them from an instance.
What I originally meant was that they would not be called from an
instance *outside* the class itself, i.e. they won't be used when
writing another script, they are only used by the class itself.
 
B

blair.bethwaite

John said:
What I originally meant was that they would not be called from an
instance *outside* the class itself, i.e. they won't be used when
writing another script, they are only used by the class itself.

Yep, so you want to encapsulate the functionality that those methods
provide, which is the whole point of building them in a class in the
first place. And you want them to be private to the class so that they
do not form part of the classes public/external interface.

In python, as discussed earlier :), you can make them semi-private by
using the '__method_name' syntax. The thing is that python doesn't
strictly enforce this privacy, code outside of your object can still
call these methods because python just mangles the internal method name
slightly. See
http://docs.python.org/tut/node11.html#SECTION0011600000000000000000
for more detail.

Cheers,
-B
 
J

John Salerno

Yep, so you want to encapsulate the functionality that those methods
provide, which is the whole point of building them in a class in the
first place. And you want them to be private to the class so that they
do not form part of the classes public/external interface.

But it's right that they should still be regular instance methods? So
from within the class I still call them as self._generate_head(), etc.?
 
J

John Salerno

John said:
But it's right that they should still be regular instance methods? So
from within the class I still call them as self._generate_head(), etc.?

I tried the underscore method, but I was still able to call it as a
regular instance method in the interpreter. Is that what's supposed to
happen?
 
D

Dennis Lee Bieber

tOn Mon, 08 May 2006 14:04:34 GMT, John Salerno
I tried the underscore method, but I was still able to call it as a
regular instance method in the interpreter. Is that what's supposed to
happen?

Single underscores are a convention/signal to the programmer that
"this method/attribute" is considered "private" and should only be used
by other methods within the class that defined it. The language does no
enforcement of usage. For example:

class Point(object):
def __init__(self, x, y):
# x, y are cartesian coordinates, but to be difficult
# the point class will use polar coordinates internally
self._rho = math.sqrt(x*x + y*y)
self._theta = #some equation to determine angle from 0

The single underscores tell the reader that rho and theta are to be
considered private implementation details, and the user of the class
should not rely on them being there. It should be possible to convert
the class to using cartesian coordinates internally without affecting
any USER -- the user interface (public methods/attributes/properties)
should not change regardless of the internal implementation.


Double underscores tell the compiler phase to do name-mangling so
that the name stays class specific should the class be inherited...

class A(object):
def __init__(self, a_datum):
super(A, self).__init__()
self.__datum = a_datum

class B(A):
def __init__(self, b_datum):
super(B, self).__init__(b_datam / 3.0)
self.__datum = b_datum

aB = B(33)

Instance "aB" now has two attributes: _A__datum and _B__datum --
both /can/ be accessed by anyone knowning the names.
['_A__datum', '_B__datum', '__class__', '__delattr__', '__dict__',
'__doc__', '__getattribute__', '__hash__', '__init__', '__module__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', '__weakref__']33

If you used single underscores, there would only be a single
"_datum" attribute, and it would have the last value assigned to it.
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
S

Scott David Daniels

John said:
I tried the underscore method, but I was still able to call it as a
regular instance method in the interpreter. Is that what's supposed to
happen?

If you called it, "__generate_head" you'd get more of what you expect.

The Python philosophy is "we're all adults here," and the single leading
underscore is meant to tell other users that the method is not for
general use. Remember, you can't stop a user who insists on making
mistakes. The double leading underscore is really meant for something
else (names in "mixin" classes that don't accidentally collide with
names in subclasses, for example).

IMO, distutils, for example, over-uses the double leading underscore
names; it makes it awkward for me to get to information that I'd like
to obtain. The double leading underscore should be there if there is
no reasonable use to getting to this info. I suspect leading double
underscore names are more frequently written by Java and C++ fugitives
who still have the "save the user from himself" attitude.

--Scott David Daniels
(e-mail address removed)
 
J

John Salerno

Dennis said:
tOn Mon, 08 May 2006 14:04:34 GMT, John Salerno


Single underscores are a convention/signal to the programmer that
"this method/attribute" is considered "private" and should only be used
by other methods within the class that defined it. The language does no
enforcement of usage. For example:

I see. But isn't there something about a single leading underscore that
doesn't import when you use from X import *? Or am I thinking of
something else? Is that also the double underscore?
 
S

Scott David Daniels

John said:
I see. But isn't there something about a single leading underscore that
doesn't import when you use from X import *? Or am I thinking of
something else? Is that also the double underscore?

That has to do with module contents, and is a completely separate issue.
If you define a module with a variable name '__all__' which is a list
(or tuple) of strings, only module elements with those names will be
imported with a "from module import *". If you fail to define the
'__all__' element, all names which do not start with an underscore will
be imported.

--Scott David Daniels
(e-mail address removed)
 
J

John Salerno

Scott said:
That has to do with module contents, and is a completely separate issue.
If you define a module with a variable name '__all__' which is a list
(or tuple) of strings, only module elements with those names will be
imported with a "from module import *". If you fail to define the
'__all__' element, all names which do not start with an underscore will
be imported.

--Scott David Daniels
(e-mail address removed)

Thanks, that's what I was thinking of. So it doesn't apply to the
contents within a class, just top-level contents?
 
S

Scott David Daniels

John said:
Thanks, that's what I was thinking of. So it doesn't apply to the
contents within a class, just top-level contents?

Precisely, a "from ... import *" only creates a bunch of names bound to
a module's top-level contents (at the time of execution of the
"from ... import *"), and does not affect anything about those bound
values (except, of course, the refcount).
 
B

bruno at modulix

John said:
Ugh, sorry about another post, but let me clarify: In these utility
functions, I need to refer to an attribute of an instance,

So you want ordinary methods.
but these
functions will be called from another method in the class, not from the
instance itself.

yes, they will:

class Parrot(object):
def _func1(self, whatever):
print whatever

def talk(self):
self._func1('vroom')
Is this even possible, or would 'self' have no meaning
when used this way?

You probably noticed that 'self' (or whatever you name it - but better
to stick to convention) *must* be defined as the first param of a
'method'. The reason for it is that what we commonly call 'methods' are
in fact plain Python functions. It's only when they are looked up on an
instance that they are wrapped into a 'method' object (read about the
descriptor protocol to learn how...), that in turn calls the function,
passing it the instance as first param.

For saying it short (warning: over-simplification ahead), the usual
method call idiom:

myObj.myMethod(arg)

is syntactic sugar for:

myObj.__class__.myMethod(myObj, arg)


HTH.
 
B

bruno at modulix

John said:
Yeah, I'm starting to see that as I tried to implement it. Here's what I
came up with, which works:

def generate(self, filename):
self.head = self.generate_head()
self.body = self.generate_body()

So the two generate_* methods are called from within another class
method,

here, generate() is *not* a class method, it's an instance method (which
is the default).
and it seemed necessary to still call them from an instance.
What I originally meant was that they would not be called from an
instance *outside* the class itself, i.e. they won't be used when
writing another script, they are only used by the class itself.

Yeps, that's pretty common in any OO language. In most mainstream OOPLs,
these methods would have the 'protected' access restriction modifier. In
Python, we rely on the convention that an attribute whose name is
prefixed with a single underscore is an implementation detail - not part
of the API - and should not be called by client code. Just renaming
these two methods is enough to warn users of your code that they're on
their own if they start messing with them.
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top