[Python-ideas] Enhancing vars()
Steven D'Aprano
steve at pearwood.info
Tue Dec 13 19:40:43 EST 2016
On Wed, Dec 14, 2016 at 12:12:39AM +0000, Emanuel Barry wrote:
> > From Steven D'Aprano
> > Sent: Tuesday, December 13, 2016 6:49 PM
> > To: python-ideas at python.org
> > Subject: Re: [Python-ideas] Enhancing vars()
> >
> > But if the object has __slots__, with or without a __dict__, then vars
> > should return a proxy which direct reads and writes to the correct slot
> > or dict.
> >
> > It might be helpful to have a slotsproxy object which provides a
> > dict-like interface to an object with __slots__ but no __dict__, and
> > build support for both __slots__ and a __dict__ on top of that.
>
> That might be a bit tricky, for example, it's possible that a class has a
> `foo` slot *and* a `foo` instance attribute (by virtue of subclasses). What
> would you do in that case?
vars() shouldn't need to care about inheritance: it only cares about the
object's own individual namespace, not attributes inherited from the
class or superclasses. That's how vars() works now:
py> class C:
... cheese = 1
...
py> obj = C()
py> ns = vars(obj)
py> 'cheese' in ns
False
The only difference here is that if the direct parent class has
__slots__, the instance will use them instead of (or in addition to) a
__dict__. We don't need to care about superclass __slots__, because they
aren't inherited.
> Or what if there's a slot that doesn't have any
> value (i.e. raises AttributeError on access, but exists on the class
> nonetheless), but an instance attribute with the same name exists? And so
> on.
Only the *list of slot names* exists on the class. The slots themselves
are part of the instance. Nevertheless, you are right: a slot can be
defined, but not assigned to. That has to be treated as if the slot
didn't exist:
py> class D:
... __slots__ = ['spam']
...
py> d = D()
py> hasattr(d, 'spam')
False
So I would expect that
'spam' in vars(d)
should likewise return False, until such time that d.spam is assigned
too.
The same applies even if the object has a __dict__. The slot always
takes precedence, even if the slot isn't filled in.
py> class E:
... __slots__ = ['spam', '__dict__']
...
py> e = E()
py> e.__dict__['spam'] = 1
py> hasattr(e, 'spam')
False
> > If the objects has *neither* __slots__ nor __dict__, vars can probably
> > raise a TypeError.
>
> Is that even possible in pure Python? The only object I know that can do
> this is `object`, but some other C objects might do that too.
I don't think pure Python classes can do this, at least not without some
metaclass trickery, but certainly `object` itself lacks both __slots__
and instance __dict__, and C objects can do the same (so I'm told).
--
Steve
More information about the Python-ideas
mailing list