[Tutor] question about "hiding" a function/method in a class

Kent Johnson kent37 at tds.net
Fri Jun 3 15:45:20 CEST 2005


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, self.default)
>          # if self.references
>          return self.fieldStr
> 
>      def __getattr__(self, attrname):
>          if attrname == "fieldStr":
>              return self.printField()
>          else:
>              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 _printField()
  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.

Kent



More information about the Tutor mailing list