[Python-Dev] Meta-reflections

john coppola john_coppola_r_s@yahoo.com
Mon, 18 Feb 2002 08:46:55 -0800 (PST)


I haven't even finished reading this yet.
This is good stuff!

--- Kevin Jacobs <jacobs@penguin.theopalgroup.com>
wrote:
> Hello all,
> 
> I've been meta-reflecting a lot lately: reflecting
> on reflection.
> 
> My recent post on __slots__ not being picklable (and
> the resounding lack of
> response to it) inspired me to try my hand at
> channeling Guido and reverse-
> engineer some of the design decisions that went into
> the new-style class
> system.  Unfortunately, the more I dug into the
> code, the more philosophical
> my questions became.  So, I've written up some
> questions that help lay bare
> some of basic design questions that I've been asking
> myself and that you
> should be aware of.
> 
> While there are several subtle issues I could raise,
> I do want some feedback
> on some simple and fundamental ones first.  Please
> don't disqualify yourself
> from commenting because you haven't read the code or
> used the new features
> yet.  I've written my examples assuming only a basic
> and cursor
> understanding of the new Python 2.2 features.
> 
>   [In this discussion I am only going to talk about
> native Python classes,
>    not C-extension or native Python types (e.g.,
> ints, lists, tuples,
>    strings, cStringIO, etc.)]
> 
>   1) Should class instances explicitly/directly know
> all of their attributes?
> 
>      Before Python 2.2, all object instances
> contained a __dict__ attribute
>      that mapped attribute names to their values. 
> This made pickling and
>      some other reflection tasks fairly easy.
> 
>         e.g.:
> 
>         class Foo:
>           def __init__(self):
>             self.a = 1
>             self.b = 2
> 
>         class Bar(Foo):
>           def __init__(self):
>             Foo.__init__(self)
>             self.c = 3
> 
>         bar = Bar()
>         print bar.__dict__
>         > {'a': 1, 'c': 3, 'b': 2}
> 
>      I am aware that there are situations where this
> simple case does not
>      hold (e.g., when implementing __setattr__ or
> __getattr__), but let's
>      ignore those for now.  Rather, I will
> concentrate on how this classical
>      Python idiom interacts with the new slots
> mechanism.  Here is the above
>      example using slots:
> 
>         e.g.:
> 
>         class Foo(object):
>           __slots__ = ['a','b']
>           def __init__(self):
>             self.a = 1
>             self.b = 2
> 
>         class Bar(Foo):
>           __slots__ = ['c']
>           def __init__(self):
>             Foo.__init__(self)
>             self.c = 3
> 
>         bar = Bar()
>         print bar.__dict__
>         > AttributeError: 'Bar' object has no
> attribute '__dict__'
> 
>      We can see that the class instance 'bar' has no
> __dict__ attribute.
>      This is because the slots mechanism allocates
> space for attribute
>      storage directly inside the object, and thus
> does not use (or need) a
>      per-object instance dictionary to store
> attributes.  Of course, it is
>      possible to request that a per-instance
> dictionary by inheriting from a
>      new-style class that does not list any slots. 
> e.g. continuing from
>      above:
> 
>         class Baz(Bar):
>           def __init__(self):
>             Bar.__init__(self)
>             self.d = 4
>             self.e = 5
> 
>         baz = Baz()
>         print baz.__dict__
>         > {'e': 5, 'd': 4}
> 
>      We have now created a class that has __dict__,
> but it only contains the
>      attributes not stored in slots!  So, should
> class instances explicitly
>      know their attributes?  Or more precisely,
> should class instances
>      always have a __dict__ attribute that contains
> their attributes?  Don't
>      worry, this does not mean that we cannot also
> have slots, though it
>      does have some other implications.  Keep
> reading...
> 
> 
>   2) Should attribute access follow the same
> resolution order rules as
>      methods?
> 
>         class Foo(object):
>           __slots__ = ['a']
>           self.a
>           def __init__(self):
>             self.a = 1
> 
>         class Bar(Foo):
>           __slots__ = ('a',)
>           def __init__(self):
>             Foo.__init__(self)
>             self.a = 2
> 
>         bar = Bar()
>         print bar.a
>         > 2
>         print super(Bar,bar).a   # this doesn't
> actually work
>         > 2 or 1?
> 
>     Don't worry -- this isn't a proposal and no,
> this doesn't actually work.
>     However, the current implementation only
> narrowly escapes this trap:
> 
>         print bar.__class__.a.__get__(bar)
>         > 2
>         print bar.__class__.__base__.a.__get__(bar)
>         > AttributeError: a
> 
>     Ok, let me explain what just happened.  Slots
> are implemented via the
>     new descriptor interface.  In short, descriptor
> objects are properties
>     and support __get__ and __set__ methods.  The
> slot descriptors are told
>     the offset within an object instance the
> PyObject* lives and proxy
>     operations for them.  So getting and setting
> slots involves:
> 
>         # print bar.a
>         a_descr = bar.__class__.a
>         print a_descr.__set__(bar)
> 
>         # bar.a = 1
>         a_descr = bar.__class__.a
>         a_descr.__set__(bar, 1)
> 
>     So, above we get an attribute error when trying
> to access the 'a' slot
>     from Bar since it was never initialized. 
> However, with a little
>     ugliness you can do the following:
> 
>         # Get the descriptors for Foo.a and Bar.a
>         a_foo_descr = bar.__class__.__base__.a
>         a_bar_descr = bar.__class__.a
>         a_foo_descr.__set__(bar,1)
>         a_bar_descr.__set__(bar,2)
> 
>         print bar.a
>         > 2
>         print a_foo_descr.__get__(bar)
>         > 1
>         print a_bar_descr.__get__(bar)
>         > 2
> 
>     In other words, the namespace for slots is not
> really flat, although
>     there is no simple way to access these hidden
> attributes 
=== message truncated ===


__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com