New-style classes and special methods

Jp Calderone exarkun at intarweb.us
Tue Feb 25 02:14:41 CET 2003


On Mon, Feb 24, 2003 at 07:52:27AM +0000, Alex Martelli wrote:
> Andrew Bennetts wrote:
> 
> > On Mon, Feb 24, 2003 at 01:23:24AM -0500, Jp Calderone wrote:
> >> 
> >>   Is this analysis of the behavior correct?  If so, what are the chances
> >>   of
> >> this being "fixed"?
> > 
> > I believe you are correct -- new-style classes only check their class, not
> > instances, for the __magic_methods__.
> 
> Exactly!  And this in turn IS a fix of the previous murky behavior,
> which still abides in classic classes only for backwards compat --
> there is no chance that the murky behavior of old will resurface,
> thankfully.
> 
> Why the old behavior was ill defined is made clearest by the fact
> that classes are just instances of types (their metaclasses).  E.g.:
> 
> When you call a class, say C(), what __call__ do you want to
> use -- C.__call__, the per-instance one, or type(C).__call__,
> the metaclass one?  Obviously the latter, or you'd have a hard
> time creating instances of any class that defines __call__.  The
> new and clearer rule does away with the murkiness.
> 
> Of course, you and I, Andrew, just unearthed a neat trick to
> still allow "per-instance customization" over on the properties
> thread -- give each instance its own custom subclass.  Maybe
> Jp Calderone will want to have a look at that thread, towards
> the end where the solution emerged by Andrew's and my joint
> efforts.  Basically it's just a question of giving the class
> whose instances have that particular need a specific __new__
> method -- howeer, you can also do it in others ways, for ex. if
> only a FEW of the instances need such customization you can
> choose to equip only those instances with their own custom
> subclasses and leave all the others to share the main class.
> 
> 
> Here's an example of the latter idea:
> 
> def setSpecialAttr(inst, name, value):
>     try:
>         inst.__customized_subclass__
>     except AttributeError:
>         class subclass(inst.__class__):
>             __customized_subclass__ = True
>         inst.__class__ = subclass
>     setattr(inst.__class__, name, value)
> 

  Thanks, this is a neat trick, I'll have to keep it in mind.  My use case
lies along different lines (I tell a lie, I have no use case, but if I did,
it would lie along these...):

    class AccessError(AttributeError): pass

    class PromiscuousPolicy:
        def allowAccess(self, name):
            return True

    class Proxy(object):
        def __init__(self, original, policy=PromiscuousPolicy()):
            self.__original = original
            self.__policy = policy

        def __getattribute__(self, name):
            p = super(Proxy, self).__getattribute__('__policy')
            if not p.allowAccess(name):
                raise AccessError
            return getattr(
                super(Proxy, self).__getattribute__('__original'),
                name
            )

  I'm not sure I see a way to apply the approach setSpecialAttr uses here...
Though, maybe Proxy could iterate over the attributes of 'original', adding
fake-out attributes to a new class object, then set its own class to that
new one... Hrm... *wanders off to play around in the interpreter*.

  Jp

-- 
 up 16 days, 4:29, 5 users, load average: 0.30, 0.12, 0.04
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20030224/153c0ca7/attachment.pgp>


More information about the Python-list mailing list