[Python-ideas] Namespace creation with syntax short form

Peter Otten __peter__ at web.de
Fri Feb 13 14:20:48 CET 2015


Andrew Barnert wrote:

> On Feb 13, 2015, at 4:05, Peter Otten
> <__peter__ at 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)




More information about the Python-ideas mailing list