Private data

Dustan DustanGroups at gmail.com
Sun Mar 18 13:35:51 CET 2007


On Mar 18, 7:17 am, "Dustan" <DustanGro... at gmail.com> wrote:
> On Mar 18, 5:26 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> wrote:
>
>
>
> > En Sat, 17 Mar 2007 13:31:01 -0300, Dustan <DustanGro... at gmail.com>
> > escribió:
>
> > >http://dustangroups.googlepages.com/privateattributesinpython
>
> > > This is something that I just threw together this morning, after a
> > > eureka moment. It's a way of creating private class attributes and
> > > static function variables (I'm not 100% sure if that's the correct
> > > terminology, but you get what I mean). I haven't tried to create
> > > private instance attributes, mainly because it would just be too
> > > difficult, and it would be awful syntax. I'm not considering actually
> > > using this, but I do have a couple questions about it.
>
> > I feel so dumb, but I can't see how to use it, or what's for. Perhaps an
> > example?
>
> > --
> > Gabriel Genellina
>
> There are two examples - one demonstrating static function variables
> and one demonstrating private class attributes. Both perform some kind
> of counting. The function returns how many times it's been called.
> Here it is:
>
> @PrivateDataEngine(numCalls = 0)
> def testPrivateStaticFunctionVariables(internalData):
>     """returns the number of times this function has been called."""
>     internalData.numCalls += 1
>     return internalData.numCalls
>
> There's a comment explaining how the decorator works on the page I
> linked you to.
>
> A common pythonic workaround for this is something like this:
>
> def testMutableDefaultArgs(_cache = {'internalData':0}):
>     """returns the number of times this function has been called."""
>     _cache['internalData'] += 1
>     return _cache['internalData']
>
> The default argument only gets evaluated once, and since it's mutable
> and being modified in the function, it magically becomes
> {'internalData':1} after 1 call and {'internalData':1348372} after
> 1348372 calls.
>
> The other example, explaining private class attributes, has a method
> getNumInstances that returns how many instances have been created.
> Here that is:
>
> class TestPrivateClassAttributes(object):
>     # pca here obviously stands for Private Class Attributes.
>     pcaManager = PrivateDataEngine(numInstances = 0)
>
>     # Notice that the internal data is an implicit parameter that
> comes first,
>     # even before the self parameter.
>     @pcaManager
>     def __init__(internalData, self):
>         internalData.numInstances += 1
>
>     @staticmethod
>     @pcaManager
>     def getNumInstances(internalData):
>         return internalData.numInstances
>
>     # Don't forget to delete the pcvManager, or it will have all been
> in vain.
>     del pcaManager
>
> I'm thinking this is going to look rather ugly when the text gets
> wrapped; that's why I linked to an external page in the first place.
>
> Notice it requires more advanced usage of the PrivateDataEngine if you
> want multiple functions to have access to the same data, as you
> normally would in a class.
>
> Note also that the double-decorated method getNumInstances requires
> that staticmethod be the first decorator. This is equivalent to the
> code "getNumInstances = staticmethod(pcaManager(getNumInstances))". I
> got an error when I tried it with pcaManager preceding staticmethod,
> so my educated guess is that staticmethods are somehow specially
> recognized by the class, and therefore they have to actually BE
> staticmethods, not dressed over by a pcaManager.
>
> Now that I think of it, for clarity, pcaManager may not have been a
> good name for the function returned by PrivateDataEngine; pcaDecorator
> would have been better, seeing as it IS a decorator. Perhaps I'll
> change that soon.
>
> The pythonic way would be:
>
> class TestPythonsPrivateClassAttributes(object):
>     _numInstances = 0
>
>     def __init__(self):
>         # class attributes can be accessed from self.
>         self.numInstances += 1
>
>     @staticmethod
>     def getNumInstances(internalData):
>         return self.numInstances
>
> It should immediately stick out as being much more concise
> syntactically, and therefore much less bug-prone.
>
> Obviously, these examples are a lot like "Hello, World!" in their
> usefulness; one would very rarely want to track how many times a
> function has been called.
>
> Hope that helps.

I forgot to note that the 'pythonic' ways are untested (and remain so,
as far as I know).




More information about the Python-list mailing list