Private variables

Ryan Kelly ryan at rfk.id.au
Wed Sep 1 22:22:21 EDT 2010


On Thu, 2010-09-02 at 12:06 +1000, Ryan Kelly wrote:
> On Thu, 2010-09-02 at 11:10 +1000, Rasjid Wilcox wrote:
> > Hi all,
> > 
> > I am aware the private variables are generally done via convention
> > (leading underscore), but I came across a technique in Douglas
> > Crockford's book "Javascript: The Good Parts" for creating private
> > variables in Javascript, and I'd thought I'd see how it translated to
> > Python. Here is my attempt.
> > 
> > def get_config(_cache=[]):
> >     private = {}
> >     private['a'] = 1
> >     private['b'] = 2
> >     if not _cache:
> >         class Config(object):
> >             @property
> >             def a(self):
> >                 return private['a']
> >             @property
> >             def b(self):
> >                 return private['b']
> >         config = Config()
> >         _cache.append(config)
> >     else:
> >         config = _cache[0]
> >     return config
> > 
> > >>> c = get_config()
> > >>> c.a
> > 1
> > >>> c.b
> > 2
> > >>> c.a = 10
> > Traceback (most recent call last):
> >   File "<string>", line 1, in <fragment>
> > AttributeError: can't set attribute
> > >>> dir(c)
> > ['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
> > '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
> > '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
> > '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b']
> > >>> d = get_config()
> > >>> d is c
> > True
> > 
> > I'm not really asking 'is it a good idea' but just 'does this work'?
> > It seems to work to me, and is certainly 'good enough' in the sense
> > that it should be impossible to accidentally change the variables of
> > c.
> > 
> > But is it possible to change the value of c.a or c.b with standard
> > python, without resorting to ctypes level manipulation?
> 
> It's not easy, but it can be done by introspecting the property object
> you created and munging the closed-over dictionary object:
> 
>    >>> c = get_config()
>    >>> c.a
>    1
>    >>> c.__class__.__dict__['a'].fget.func_closure[0].cell_contents['a'] = 7
>    >>> c.a
>    7
>    >>> 


Heh, and of course I miss the even more obvious trick of just clobbering
the property with something else:

  >>> c.a
  1
  >>> setattr(c.__class__,"a",7)
  >>> c.a
  7
  >>> 


   Ryan


-- 
Ryan Kelly
http://www.rfk.id.au  |  This message is digitally signed. Please visit
ryan at rfk.id.au        |  http://www.rfk.id.au/ramblings/gpg/ for details

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://mail.python.org/pipermail/python-list/attachments/20100902/acbb6988/attachment-0001.sig>


More information about the Python-list mailing list