[Python-Dev] __set_foo__ et al. (PEP-able)

M.-A. Lemburg mal@lemburg.com
Thu, 20 Jul 2000 23:42:32 +0200


Paul Prescod wrote:
> 
> "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.

Huh ? "if attribute_to_set == ..." looks like a switch on 
attribute name to me.

> > > 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.

__get_foo__ causes a Python function call and this is about
the most costly activity there is in Python's internals.
 
> > 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__.

Sure, I meant proxies as good starting point for meta
classes which deal with your proposed technique. BTW, proxies
written in C are fast -- __getattr__ in C is within
practical range.
 
> > 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:

(Note: I described my personal style -- not as general rule or
guideline.)
 
>  * 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
>         else:
>            raise TypeError
> 
>    def __get_enddate__(self, val):
>         return self.endday, self.endmonth, self.endyear
> 
>    obj.enddate=(15, 12, 2000)
>    print obj.endday
>    print obj.endmonth
>    print obj.endyear
> 
>    d,m,y=obj.enddate

Well, yes. It works. But tell me: how are you going to debug
this ? Assignments will suddenly raise exceptions and the
traceback won't be of any use for programmers to find the
true error location.

Too much magic and too many possibilities for overloading
dots ;-)

(I've never understood why Javascript causes a new URL to be shown
when your assign to top.window.location.)

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/