On 2 September 2010 12:22, Ryan Kelly <r...@rfk.id.au> wrote: > 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
Ah! That is what I was looking for. > 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 Well, that is just cheating! :-) Anyway, thanks for that. I still think it is 'good enough' for those cases where private variables are 'required'. In both cases one has to go out of ones way to modify the attribute. OTOH, I guess it depends on what the use case is. If it is for storing a secret password that no other part of the system should have access to, then perhaps not 'good enough' at all. Cheers, Rasjid. -- http://mail.python.org/mailman/listinfo/python-list