Re: [Python-ideas] Enhancing vars()

2016-12-12 Thread Steve Dower
I'm +1. This bites me far too often.

> in the past developers
were encouraged to put only "useful" attributes in __dir__.

Good. If I'm getting vars() I really only want the useful ones. If I need 
interesting/secret ones then I'll getattr for them.

Cheers,
Steve

Top-posted from my Windows Phone

-Original Message-
From: "Alexander Belopolsky" 
Sent: ‎12/‎12/‎2016 19:47
To: "Steven D'Aprano" 
Cc: "python-ideas" 
Subject: Re: [Python-ideas] Enhancing vars()



On Mon, Dec 12, 2016 at 6:45 PM, Steven D'Aprano  wrote:

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.

How do you propose dealing with classes defined in C?  Their objects don't have 
__slots__.


One possibility is to use __dir__ or dir(), but those can return anything and 
in the past developers
were encouraged to put only "useful" attributes in __dir__.___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Enhancing vars()

2016-12-12 Thread Alexander Belopolsky
On Mon, Dec 12, 2016 at 6:45 PM, Steven D'Aprano 
wrote:

> 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.
>

How do you propose dealing with classes defined in C?  Their objects don't
have __slots__.

One possibility is to use __dir__ or dir(), but those can return anything
and in the past developers
were encouraged to put only "useful" attributes in __dir__.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Enhancing vars()

2016-12-12 Thread Ethan Furman

On 12/12/2016 03:45 PM, Steven D'Aprano wrote:


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.


+1

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Enhancing vars()

2016-12-12 Thread Terry Reedy

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

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Enhancing vars()

2016-12-12 Thread Steven D'Aprano
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:

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?



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/