On Tue, Dec 29, 2020 at 09:02:10AM -0800, Guido van Rossum wrote:
> On Tue, Dec 29, 2020 at 8:11 AM Steven D'Aprano <st...@pearwood.info> wrote:

> To the contrary, vars() is something I added to the language for the
> benefit of REPL users (like dir()), and other usages look suspect to me. I
> find that using `__dict__` is more direct about the purpose, and also it is
> the prevailing style.

I cannot argue with your historical perspective on this, and I agree 
that `vars()` is not as well known as I believe it should be.

So you are right on the bare facts. I still think you are wrong on the 
aesthetics :-)

Your comment also shines some light on why `vars()` with no argument 
returns `locals()`, which otherwise seems strange to me.

Nevertheless, I have to ask what could possibly be "suspect" about using 
vars() programmatically? It isn't like dir().

dir() is certainly a convenience function for interactive use, and is 
documented as returning "the most relevant, rather than complete, 
information".

This note is repeated again later in the docs: "Because dir() is 
supplied primarily as a convenience for use at an interactive prompt, it 
tries to supply an interesting set of names more than it tries to supply 
a rigorously or consistently defined set of names, and its detailed 
behavior may change across releases."

On the other hand, `vars()` has no such warnings. There's no wiggle- 
room: it either returns the instance `__dict__` or it raises TypeError. 
So aside from the difference in exceptions (AttributeError versus 
TypeError) I don't think that there is any possible difference between 
direct attribute access and the output of vars(). Am I wrong?

Speaking of slots, I've often been annoyed that there is no abstraction 
that hides the difference between instances that use a dict as symbol 
table, and those that use slots. (And those that use both.) If you need 
an object's symbol table, for introspection or otherwise, you're out of 
luck if it uses slots.

There doesn't seem to be any way to handle these two implementations in 
the same way, and objects with both slots and a dict can give surprising 
results if naive code expects `__dict__` to be the symbol table:


>>> class A:
...     __slots__ = ('spam', '__dict__')
... 
>>> obj = A()
>>> obj.spam = True
>>> 'spam' in obj.__dict__
False
>>> obj.__dict__.update(spam=False)
>>> obj.spam
True


So there's no way to get an object's symbol table in an implementation- 
independent way. Whether you use `obj.__dict__` or `vars(obj)` it only 
gives you the symbol table for objects that use a dict. There's nothing 
that works for objects that use slots.

So far I've worked around this in an ad-hoc fashion by testing for 
`__slots__` and treating that case as special, but it would be nice to 
ignore the implementation details and just have a "symbol table" object 
to work with. What do you think?


> > Do you prefer to write `mylist.__len__()` over `len(mylist)`? Then you
> > will probably prefer `obj.__dict__` over `vars(obj)` too :-)
> >
> 
> Not a valid analogy.

I think it is. Apart from a matter of taste, what part of the analogy 
do you feel is invalid?



-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FPVQS2EHXP3LQMDO67R4N46PAEOLJQBR/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to