Help with changes in traceback stack from Python 2.7 to Python 3.x

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Apr 27 22:11:30 EDT 2014


On Sun, 27 Apr 2014 21:51:54 +0000, Andrew Konstantaras wrote:

> I guess I am missing something big as I am looking for a shorthand way
> of doing the following:
> 
>            dctA = dict(x=x, y=y, ... n=n)
> 
> This is, as I understand it a very natural way of using a dictionary. 

Would you prefer this?

    dctA = {'x': x, 'y': y, 'n': n}


> It seems that this syntax is unnecessarily redundant 
[...]
> I will give the locals approach a try, it seems a little more clumsy
> than simply passing the variables to the function.


If you think that, it's because you haven't really thought it through 
completely. Possibly you don't quite understand Python's execution model 
fully, or you're used to languages which have a different execution 
model, or worst of all, you're used to a language which blesses dirty 
runtime hacks as "features".

Suppose we could pass variables directly to the constructor, like this:

a = b = 2
L = [1, 2, 3]
dctA = dict(a, b, L[1], 2, 1+1)

Obviously all five values are 2, but what are the keys?

A language with a static compiler and pass-by-name behaviour, like Algol, 
might be able to tell that the first argument comes from a variable 
called 'a' and the second from a variable called 'b'. But languages with 
pass-by-value behaviour, like C, cannot.

Likewise, Python cannot tell the name of the object. The dict construct 
receives five arguments, all bound to the object 2. (That might be the 
same object five times, or five distinct objects, all with the same value 
of 2.) The objects don't know what names they are bound to: they might be 
bound to zero, one, or more names. If they're bound to zero names, what 
name should the dict constructor invent for them? If they're bound to two 
or more names, which name should the dict constructor use?

So as you can see, in general the dict constructor *cannot* infer a 
unique name for the argument. In some cases it may be able to guess, or 
arbitrarily pick one out of many, using implementation hacks that are not 
standard across all versions and implementations of Python. A hack that 
works in CPython probably won't work in Jython, and one that works in 
IronPython probably won't work in PyPy.

Objects don't have a unique name, so the very concept of getting "the 
name" of a value is dubious, and has to rely on a dirty hack. 
Nevertheless, as you have discovered, you can do so in CPython. 
Presumably there is a different hack that would work in IronPython, 
Jython, Cython, PyPy, Nuitka, Unladen Swallow, ... so perhaps it could be 
declared that, dirty hack or not, it should be part of the language. 
Should it?

Consider the unlimited number of variations on:

dict(key=value)
dict(name=value)
dict(age=value)
dict(a=value)
dict(b=value)
dict(arg=value)
dict(param=value)
dict(foo=value)
dict(bar=value)
[...]
dict(value=value)

Why is that last case so special that the dict constructor should guess 
that when you type "dict(value)" it wasn't a mistake, but that you 
actually intended "dict(value=value)" rather than key=value or name=value?

You should consider the Zen of Python for a glimpse into the design 
principles that the creators of Python tend to follow as a rule:

http://legacy.python.org/dev/peps/pep-0020/

See how many of the design principles are violated by a feature that 
guesses the key name if not supplied.

Other languages may make other choices. I think that makes them worse 
languages.



-- 
Steven D'Aprano
http://import-that.dreamwidth.org/



More information about the Python-list mailing list