[Python-Dev] __set_foo__ et al. (PEP-able)
Thu, 20 Jul 2000 16:18:08 -0500
"M.-A. Lemburg" wrote:
> > def __setattr__( name, val ):
> > if attribute_to_set=="__class__":
> > assert PyClass_Check( val ):
> > elif attribute_to_set=="__dict__":
> > assert PyDict_Check( val ):
> But that's just an implementation detail (you either do the
> lookup via a mapping, e.g. the instance dict, or by switching
> on the attribute name)... in C and with only a few cases, the
> switching technique is faster than the lookup.
That's not the case. In this case, Guido is doing type checking on sets.
You can only do that in Python with an __setattr__ hack.
> > It's just a cleaner, Pythonic way to do something that is already common
> > either using __getattr__ hacks or in extension modules.
> It's also *much* slower: you'd have to check objects for
> e.g. obj.__set_foo__ prior to every obj.foo=1 assignment.
It's much, much faster for than __getattr__ for gets. It's probably no
slower than __setattr__ for sets because you aren't switching on the
attribute name in Python. Anyhow gets are much more common than sets so
speeding them up is a big win.
> I think that these techniques are better implemented by
> writing a special proxy which then does your proposed
> mapping for a predefined set of attributes.
Proxies are slow and introduce a host of their own "issues." In
practice, I've never seen anyone implement this pattern with proxies
unless the proxies were doing something else already (e.g. COM). They
always use a direct __getattr__/__setattr__.
> I usually use the direct attribute access method for
> information containers and the method access for more
> elaborate objects (ones which care about the data format,
> apply extra checks, depend on state, etc.). Very often
> these methods set more than just one attribute, so using
> __set_foo__ wouldn't work here.
Don't follow. Here's an example that:
* cares about data format
* applies extra checks
* is state dependent
* sets more than one attribute internally
def __set_enddate__( self, val ):
if len(val)==3 and val>self.start_date
self.endday, self.endmonth, self.endyear=val
def __get_enddate__(self, val):
return self.endday, self.endmonth, self.endyear
obj.enddate=(15, 12, 2000)
Paul Prescod - Not encumbered by corporate consensus
"Hardly anything more unwelcome can befall a scientific writer than
having the foundations of his edifice shaken after the work is
finished. I have been placed in this position by a letter from
Mr. Bertrand Russell..."
- Frege, Appendix of Basic Laws of Arithmetic (of Russell's Paradox)