[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