Private class and instance methods?

Mark Pilgrim f8dy at diveintopython.org
Sat Mar 10 16:04:14 EST 2001


in article 3AAA73BF.9CDCF3B2 at alcyone.com, Erik Max Francis at
max at alcyone.com wrote on 3/10/01 1:34 PM:
> How often do people use methods beginning with __ in order to get some
> amount of privacy with the automatic name mangling that occurs, to get
> some kind of weak protection, with, say, accessor methods:
> 
> class C:
> def __init__(self, x):
> self.__x = x
> 
> def getX(self): return self.__x
> def setX(self, x): self.__x = x
> 
> [which would of course allow C.getX and C.setX to do something different
> in the future]?

There is a better way to do this in Python, using the __getattr__ and
__setattr__ special methods.

class foo:
    privatekeys = ('x',)
    
    def __init__(self, x):
        self.x = x
    def __getattr__(self, key):
        print "getting private value %s" % key
        return self.__dict__['__%s' % key]
    def __setattr__(self, key, value):
        if key in self.__class__.privatekeys:
            print "setting private value %(key)s to %(value)s" % locals()
            self.__dict__['__%s' % key] = value
        else:
            self.__dict__[key] = value

if __name__=='__main__':
    f = foo('abc')
    print "f.x = %s" % f.x
    f.y = []
    print "f.y = %s" % f.y
    f.x = 10
    print "f.x = %s" % f.x
    
Running the example script produces this output (minus the comments):

setting private value x to abc # from __init__ method
getting private value x # from getting f.x in first print in main block
f.x = abc # output of 1st print
f.y = [] # output of 2nd print
setting private value x to 10 # from setting f.x
getting private value x # from getting f.x in 3rd print
f.x = 10 # output of 3rd print

There is no f.x (insert gratuitous reference to "The Matrix" here), because
whenever you try to set it, Python calls __setattr__ and you end up setting
f.__x instead, and whenever you try to get it, Python calls __getattr__ and
you end up getting f.__x instead.

f.y does exist, just like a normal public attribute.

You can control which attributes are redirected by adding their names to the
class attribute "privatekeys".

More on special methods:
  http://diveintopython.org/fileinfo_specialmethods.html
  http://www.python.org/doc/current/ref/specialnames.html

More on class attributes:
  http://diveintopython.org/fileinfo_classattributes.html

Hope this helps.

-M
You're smart; why haven't you learned Python yet?
http://diveintopython.org/






More information about the Python-list mailing list