Getters and Setters
Bernhard Herzog
herzog at online.de
Thu Jul 15 06:19:47 EDT 1999
Andrew Dalke <dalke at bioreason.com> writes:
> Neil Schemenauer <nascheme at ucalgary.ca> proposed:
> > # A mixin class to automagicly create getter/setter methods for
> > # class attributes.
> Here's one optimization, don't recreate getter/setter objects.
> How about this:
>
> class GetterSetter:
> def __getattr__(self, name):
> try:
> if name[:3] == 'get':
> x = _Getter(self.__dict__[name[3:]])
> self.__dict__[name] = x
> return x
It seems to me that this way, the get* method will always return the
same value, the value of the instance variable when the _Getter was
first instantiated, even if the instance variable changed later.
> elif name[:3] == 'set':
> x = _Setter(self, name[3:])
> self.__dict__[name] = x
> return x
And this one will introduce a circular reference
> except KeyError:
> pass
> raise AttributeError
> Since your timing test does so many repeats (esp. when I increase
> n :), that suggests I can take a 1-time cost per attribute, so
> I can use an eval.
>
> class GetterSetter:
> def __getattr__(self, name):
> try:
> if name[:3] == 'get':
> #x = _Getter(self.__dict__[name[3:]])
> val = self.__dict__[name[3:]]
> x = eval("lambda :x", {"x": val})
> self.__dict__[name] = x
> return x
This has the same problems as above, i.e. the method always returns the
same value.
> elif name[:3] == 'set':
> x = _Setter(self, name[3:])
> self.__dict__[name] = x
> return x
> except KeyError:
> pass
> raise AttributeError
> For my final trick, I'll do the same to the Setter:
> import operator
> class GetterSetter:
> def __getattr__(self, name):
> try:
> if name[:3] == 'get':
> #x = _Getter(self.__dict__[name[3:]])
> val = self.__dict__[name[3:]]
> x = eval("lambda :x", {"x": val})
> self.__dict__[name] = x
> return x
> elif name[:3] == 'set':
> x = eval("lambda val: set(dict, %s, val)" % `name[3:]`,
> {"dict": self.__dict__, "set": operator.setitem})
> #x = _Setter(self, name[3:])
> self.__dict__[name] = x
And again a circular reference.
> return x
> except KeyError:
> pass
> raise AttributeError
> It's only about 10% slower, though for n==10 it's still about
> 8 times slower. And it has a nasty case of cyclical references
> (since __dict__ caches the lambda functions, which contain
> a reference to __dict__). I'll leave cleaning that up as an
> exercise to the student :)
Oh. I should have read the entire post before writing my reply :)
--
Bernhard Herzog | Sketch, a python based drawing program
herzog at online.de | http://www.online.de/home/sketch/
More information about the Python-list
mailing list