Copy constructors
Andrew Dalke
dalke at acm.org
Tue Aug 14 07:05:00 EDT 2001
Guido:
>No, in the new system, __getattr__ is called for all attributes. See
>my response to Roman.
I hadn't noticed this __getattr__ change on my previous readings.
I confess I couldn't find that response - perhaps my newsserver
dropped it? But I do see a post of yours with no attribution of
who you are responding to, which says:
> new-style classes allow you to
> overload __getattr__ for all attribute accesses -- classic classes
> only call __getattr__ when "normal" attribute access fails, which is
> less flexible.
I want to point out that the current ("old-style") behaviour is
very usful for caching results. I have written several classes
of the form
class Obj:
def __getattr__(self, name):
if name == "prop1":
compute prop1
self.prop1 = prop1
return prop1
elif name == "prop2":
...
raise AttributeError(name)
For example, one is a system where the "compute prop" calls a
C function, and another version talks to a database to get the
requested information.
In both cases, I liked the simplicity of implementation and the
fact that once cached there is no performance loss.
With the new-style __getattr__ this means the code will be
slightly more complicated, as in
def __getattr__(self, name):
if name in self.__dict__:
return self.__dict__[name]
... code as usual ...
and definitely slower.
Yes, I am concerned about the performance. Instead of using
__getattr__/__setattr__ to mimic attribute lookup I could also
have done C++/Java style accessor methods
def getProp1(self):
...
def setProp1(self):
...
I happen to think accessor functions look ugly - things that
are attributes should look like attributes. I've been able to
argue against them because __*attr__ exists partially because I
can say "and the results can be cached with no performance loss."
But now it appears that getProp1()/setProp1() methods will never
be slower than __getattr__, so I will only have an esthetic
argument to justify my preference.
I do understand that not having a __getattr__ hook for all attribute
lookups is less flexible. I just not that I've much more often
used this caching lookup ability than needed that flexibility. In
fact, I'm hard pressed to think of a case where I have needed more
flexibility.
>I'd like to see which is more common -- the need to change __class__
>or the need to inherit from a built-in type. I'm betting the latter,
>by a large amount.
I've derived from UserList and UserDict, many more times then I've
changed __class__. I've also derived from them many more than I've
used the dis, netrc, or mailcap modules, or used complex numbers
or unicode, or specified a PYTHONSTARTUP variable for interactive use.
Should those features also be removed?
Andrew
dalke at dalkescientific.com
More information about the Python-list
mailing list