[Python-ideas] Enhancing vars()
Terry Reedy
tjreedy at udel.edu
Mon Dec 12 21:21:02 EST 2016
On 12/12/2016 6:45 PM, Steven D'Aprano wrote:
> In general, directly accessing dunders is a bit of a code smell. (I
> exclude writing dunder methods in your classes, of course.) There's
> usually a built-in or similar to do the job for you, e.g. instead of
> iterator.__next__() we should use next(iterator).
>
> One of the lesser-known ones is vars(obj), which should be used in place
> of obj.__dict__.
>
> Unfortunately, vars() is less useful than it might be, since not all
> objects have a __dict__. Some objects have __slots__ instead, or even
> both. That is considered an implementation detail of the object.
>
> Proposal: enhance vars() to return a proxy to the object namespace,
> regardless of whether said namespace is __dict__ itself, or a number of
> __slots__, or both. Here is a woefully incompete and untested prototype:
+1 I believe this was mentioned as a possibility on some issue , but I
cannot find it. Does vars currently work for things with dict proxies
instead of dicts?
> class VarsProxy(object):
> def __init__(self, obj):
> if not (hasattr(obj, '__dict__') or hasattr(obj, '__slots__')):
> raise TypeError('object has no namespace')
> self._obj = obj
>
> def __getitem__(self, key):
> slots = getattr(type(self), '__slots__', None)
> # see inspect.getattr__static for a more correct implementation
> if slots is not None and key in slots:
> # return the content of the slot, without any inheritance.
> return getattr(self._obj, key)
> else:
> return self._obj.__dict__[key]
>
> def __setitem__(self, key, value): ...
> def __delitem__(self, key): ...
>
>
>
> One complication: it is possible for the slot and the __dict__ to
> both contain the key. In 3.5 that ambiguity is resolved in favour of the
> slot:
>
> py> class X:
> ... __slots__ = ['spam', '__dict__']
> ... def __init__(self):
> ... self.spam = 'slot'
> ... self.__dict__['spam'] = 'dict'
> ...
> py> x = X()
> py> x.spam
> 'slot'
>
>
> Although __slots__ are uncommon, this would clearly distinguish
> vars(obj) from obj.__dict__ and strongly encourage the use of vars()
> over direct access to the dunder attribute.
>
>
> Thoughts?
>
>
>
--
Terry Jan Reedy
More information about the Python-ideas
mailing list