
Andrew Barnert wrote:
On Feb 13, 2015, at 4:05, Peter Otten <__peter__@web.de> wrote:
Steven D'Aprano wrote:
On Fri, Feb 13, 2015 at 11:19:58AM +0100, Morten Z wrote:
Namespaces are widely used in Python, but it appear that creating a namespace has no short form, like [] for list or {} for dict, but requires the lengthy types.SimpleNamespace, with prior import of types.
from types import SimpleNamespace as NS ns = NS(answer=42)
Python did without a SimpleNamespace type for 20+ years. I don't think it is important enough to deserve dedicated syntax, especially yet another overloading of parentheses. Not everything needs to be syntax.
If there were syntactic support for on-the-fly namespace "packing" and "unpacking" that could have a significant impact on coding style, similar to that of named arguments.
Functions often start out returning a tuple and are later modified to return a NamedTuple. For backward compatibility reasons you are either stuck with the original data or you need a workaround like os.stat_result which has more attributes than items.
There's really nothing terrible about that workaround, except that it's significantly harder to implement in Python (with namedtuple) than in C (with structseq).
More importantly, I don't see how named unpacking helps that. If your function originally returns a 3-tuple, and people write code that expects a 3-tuple, how do you change it to return a 3-tuple that's also a 4-namespace under your proposal?
Meanwhile:
"Named (un)packing" could avoid that.
def f(): ... return a:1, b:2, c:3 f() (a:1, b:2, c:3)
So what type is that? Is there a single type for all "named packing tuples" (like SimpleNamespace), or a separate type for each one (like namedtuple), or some kind of magic that makes issubclass(a, b) true if b has the same names as a plus optionally more names at the end, or ...?
I'm an adept of duck typing, so a:1, b:2, c:3 has to create an object with three attributes "a", "b", and "c" and :a, :b, :c = x works on any x with three attributes "a", "b", and "c". Implementationwise
some kind of magic that makes issubclass(a, b) true if b has the same names as a plus optionally more names at the end, or ...?
would be OK, but as there is no order of the names there is also no "end". In general this should start as restrictive as possible, e. g. issubclass(type(a), type(b)) == a is b wouldn't bother me as far as usability is concerned.
How does this interact with existing unpacking? Can I extract the values as a tuple, e.g., "x, *y = f()" to get x=1 and y=(2, 3)? Or the key-value pairs with "**kw = f()"? Or maybe ::kw to get them as a namespace instead of a dict? Can I mix them, with "x, *y, z:c" to get 1, (2,), and 3 (and likewise with **kw or ::ns)?
I'd rather not mix positional and and named (un)packing.
Does this only work with magic namespaces, or with anything with attributes? For example, if I have a Point class, "does x:x = pt" do the same thing as "x = pt.x", or does that only work if I don't use a Point class and instead pass around (x:3, y:4) with no type information?
Since the parens are clearly optional, does that mean that "a:3" is a single-named namespace object, or do you need the comma as with tuples? (I think the former may make parsing ambiguous, but I haven't thought it through...)
No comma, please, if at all possible.
:c, :b, :a = f() # order doesn't matter :a, :c = f() # we don't care about b a # by default bound name matches attribute name
Why do you need, or want, that last comment? With similar features, you have to be explicit; e.g., if you want to pass a local variable named a to a keyword parameter named a, you have to write a=a, not just =a. How is this case different?
I expect the bound name to match that of the attribute in ninety-nine percent or so. Other than that -- no difference.
1
x:a, y:c = f() # we want a different name x, y (1, 3)