[Tutor] question about "hiding" a function/method in a class
mhansen at cso.atmel.com
Fri Jun 3 20:54:01 CEST 2005
> Re: [Tutor] question about "hiding" a function/method in a class
> Kent Johnson <kent37 at tds.net>
> Fri, 03 Jun 2005 09:45:20 -0400
> tutor at python.org
> Mike Hansen wrote:
>> class DBField(object):
>> def __init__(self, fieldName):
>> self.fieldName = fieldName
>> self.type = ""
>> self.size = 0
>> self.notNull = False
>> self.unique = False
>> self.references = ""
>> self.default = ""
>> def printField(self):
>> self.fieldStr = " %s %s" %(self.fieldName, self.type)
>> if self.size > 0:
>> self.fieldStr = "%s(%s)" %(self.fieldStr, self.size)
>> if self.notNull:
>> self.fieldStr = "%s NOT NULL" %self.fieldStr
>> if self.unique:
>> self.fieldStr = "%s UNIQUE" %self.fieldStr
>> if self.default:
>> self.fieldStr = "%s DEFAULT %s" %(self.fieldStr,
>> # if self.references
>> return self.fieldStr
>> def __getattr__(self, attrname):
>> if attrname == "fieldStr":
>> return self.printField()
>> raise AttributeError, attrname
>> I was wondering if I should "hide" the printField function, so I or
>> someone else won't do x.printField() in the main program but use the
>> x.fieldStr attribute. If so, how would I do that, def
>> __printField(self):? How would I call it from __getattr__? I know I'm
>> not really hiding it ;just mangling it. On the other hand, I guess it
>> doesn't matter. What do you think?
> Python programmers tend to take the attitude "We're all adults here"
> towards things like this. We use conventions to put warning labels where
> appropriate, then trust the client programmer to do what is right for them.
> So, to answer your direct question, yes, you could call the method
> __printField(), which nominally hides the name from other modules, or
> _printField(), which by convention marks the method as for internal use
> only (a warning label). You would call it from __getattr__() as
> __printField() or _printField(). (A quick experiment would have answered
> this part of the question.)
> However, for your particular usage of dynamically computing the value of
> a field, there is a better way to do this - use a property.
> class DBField(object):
> def _printField(self):
> # Create a read-only fieldStr attribute whose value is computed by
> fieldStr = property(_printField)
> # Remove _printField so it can't be called directly
> del _printField
> A few more comments:
> - The name _printField() is a bit of a misnomer since nothing is
> printed; _getFieldStr() might be a better name.
> - Another, simpler way to do this is to define __str__() instead of
> _printField() and fieldStr; then clients can just call str(field) to get
> the string representation. This will work well if you don't need any
> other string representation.
> - Of course you could also just define getFieldStr() and forget about
> the fieldStr attribute entirely. This is also a very simple,
> straightforward approach.
Doh, I forgot about properties! If I had read a little more in Learning Python
on the page with __getattr__, I might have noticed properties.
I might go with the "Simple is better than complex" approach using getFieldStr().
I agree that printField wasn't sounding like a good name.
Thanks for the comments.
More information about the Tutor