[Python-Dev] Meta-reflections

Samuele Pedroni pedroni@inf.ethz.ch
Fri, 22 Feb 2002 01:38:27 +0100


From: Tim Peters <tim.one@comcast.net>
> [Tim]
> > Slots were definitely intended as a memory optimization, and the ways in
> > which they don't act like "regular old attributes" are at best warts.
>
> [Samuele Pedroni]
> > I see, but it seems that the only way to coherently and transparently
> > remove the warts implies that the __dict__ of a new-style class
> > instance with slots should be tied with the instance and cannot
> > be anymore a vanilla dict. Something only Guido can rule about.
>
> He'll be happy to <wink>.  Optimizations aren't always wart-free, and then
> living with warts is a price paid for benefiting from the optimization.  I'm
> sure Guido would consider it "a bug" if slots are ignored by the pickling
> mechanism, but wouldn't for an instant consider it "a bug" that the set of
> slots in effect when a class is created can't be dynamically expanded later
> (this latter is more a sensible restriction than a wart, IMO -- and likely
> in Guido's too).
>

I was thinking along the line of the C equiv of this:
[Yup the situation of a subclass of a class with slots
is more relevant]

class C(object):
  __slots__ = ['_a']


class D(C): pass


def allslots(cls):
  mro = list(cls.__mro__)
  mro.reverse()
  allslots = {}
  for c in mro:
    cdict = c.__dict__
    if '__slots__' in cdict:
      for slot in cdict['__slots__']:
        allslots[slot] = cdict[slot]
  return allslots

class slotdict(dict):
   __slots__ = ['_inst','_allslots']
   def __init__(self,inst,allslots):
     self._inst = inst
     self._allslots = allslots

   def __getitem__(self,k):
     if self._allslots.has_key(k):
        # self _allslots should be reachable as
self._inst.__class__.__allslots__
        # AttributeError should become a KeyError ?
        return self._allslots[k].__get__(self._inst)
     else:
        return dict.__getitem__(self,v)

   def __setitem__(self,k,v):
     if self._allslots.has_key(k):
        # self _allslots should be reachable as
self._inst.__class__.__allslots__
        # AttributeError should become a KeyError ?
        return self._allslots[k].__set__(self._inst,v)
     else:
        return dict.__setitem__(self,v)

   # other methods accordingly

d=D()
d.__dict__ = slotdict(d,allslots(D)) # should be so automagically

# allslots(D) should be probably accessible as d.__class__.__allslots__
# for transparency C.__dict__ should not contain any slot descr

#  __allslots__ should be readonly and disallow rebinding
# d.__dict__ should disallow rebinding

# c =C() ; c.__dict__ should return a proxy dict lazily or even more so ...

Lots of things to rule about and trade-offs to consider.

the-more-it's-arbitrary-the-more-you-need-_one_-ruler-ly y'rs - Samuele.