New-style classes and special methods
Jp Calderone
exarkun at intarweb.us
Mon Feb 24 20:14:41 EST 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.sig>
More information about the Python-list
mailing list