Re: [Python-ideas] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Steven D'Aprano
On Wed, Jul 26, 2017 at 11:58:44AM +1200, Greg Ewing wrote:

> If we're going to have such a type, I suggest making it a
> pure named-fields object without any tuple aspects. In which
> case "ntuple" wouldn't be the right name for it, and something
> like "record" or "struct" would be better.

Guido's time machine strikes again. 

from types import SimpleNamespace


By the way: records and structs define their fields in a particular 
order too. namedtuple does quite well at modelling records and structs 
in other languages.


> Also, building a whole type object for each combination of
> fields seems like overkill to me. Why not have just one type
> of object with an attribute referencing a name-to-slot
> mapping?

You mean one globally shared mapping for all ntuples? So given:

spam = ntuple(name="fred", age=99)
eggs = ntuple(model=2, colour="green")

we would have spam.colour == 99, and eggs.name == 2.


Personally, I think this whole proposal for implicitly deriving type 
information from the way we instantiate a tuple is a bad idea. I don't 
see this becoming anything other than a frustrating and annoying source 
of subtle, hard to diagnose bugs.


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


Re: [Python-ideas] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Steven D'Aprano
On Tue, Jul 25, 2017 at 08:30:14PM +0100, MRAB wrote:

> Given:
> 
> >>> nt = ntuple(x=1, y=2)
> 
> you have nt[0] == 1 because that's the order of the args.
> 
> But what about:
> 
> >>> nt2 = ntuple(y=2, x=1)
> 
> ? Does that mean that nt[0] == 2? Presumably, yes.

It better be.

> Does nt == nt2?
> 
> If it's False, then you've lost some of the advantage of using names 
> instead of positions.

Not at all. It's a *tuple*, so the fields have a definite order. If you 
don't want a tuple, why are using a tuple? Use SimpleNamespace for an 
unordered "bag of attributes":

py> from types import SimpleNamespace
py> x = SimpleNamespace(spam=4, eggs=3)
py> y = SimpleNamespace(eggs=3, spam=4)
py> x == y
True

> It's a little like saying that functions can be called with keyword 
> arguments, but the order of those arguments still matters!

That's the wrong analogy and it won't work. But people will expect that 
it will, and be surprised when it doesn't!


The real problem here is that we're combining two distinct steps into 
one. The *first* step should be to define the order of the fields in the 
record (a tuple): [x, y] is not the same as [y, x]. Once the field order 
is defined, then you can *instantiate* those fields either positionally, 
or by name in any order.

But by getting rid of that first step, we no longer have the option to 
specify the order of the fields. We can only infer them from the order 
they are given when you instantiate the fields.

Technically, Nick's scheme to implicitly cache the type could work 
around this at the cost of making it impossible to have two types with 
the same field names in different orders. Given:

ntuple(y=1, x=2)

ntuple could look up the *unordered set* {y, x} in the cache, and if 
found, use that type. If not found, define a new type with the fields in 
the stated order [y, x].

So now you can, or at least you will *think* that you can, safely write 
this:

spam = ntuple(x=2, y=1, z=0)  # defines the field order [x, y, z]
eggs = ntuple(z=0, y=1, x=2)  # instantiate using kwargs in any order
assert spam=eggs


But this has a hidden landmine. If *any* module happens to use ntuple 
with the same field names as you, but in a different order, you will 
have mysterious bugs:

x, y, z = spam

You expect x=2, y=1, z=0 because that's the way you defined the field 
order, but unknown to you some other module got in first and defined it 
as [z, y, x] and so your code will silently do the wrong thing.

Even if the cache is per-module, the same problem will apply. If the 
spam and eggs assignments above are in different functions, the field 
order will depend on which function happens to be called first, which 
may not be easily predictable.

I don't see any way that this proposal can be anything by a subtle 
source of bugs. We have two *incompatible* requirements:

- we want to define the order of the fields according to the 
  order we give keyword arguments;

- we want to give keyword arguments in any order without 
  caring about the field order.

We can't have both, and we can't give up either without being a 
surprising source of annoyance and bugs.

As far as I am concerned, this kills the proposal for me. If you care 
about field order, then use namedtuple and explicitly define a class 
with the field order you want. If you don't care about field order, use 
SimpleNamespace.



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


Re: [Python-ideas] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Greg Ewing

Nick Coghlan wrote:


New builtin:

ntuple(x=1, y=0)


Do we really want this to be a tuple, with ordered fields?
If so, what determines the order? If it's the order of the
keyword arguments, this means that

   ntuple(x=1, y=0)

and

   ntuple(y=0, x=1)

would give objects with different behaviour.

This goes against the usual expectation that keyword arguments
of a constructor can be written in any order. That's one of
the main benefits of using keyword arguments, that you don't
have to remember a specific order for them.

If we're going to have such a type, I suggest making it a
pure named-fields object without any tuple aspects. In which
case "ntuple" wouldn't be the right name for it, and something
like "record" or "struct" would be better.

Also, building a whole type object for each combination of
fields seems like overkill to me. Why not have just one type
of object with an attribute referencing a name-to-slot
mapping?

--
Greg
___
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] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Giampaolo Rodola'
On Thu, Jul 20, 2017 at 3:35 AM, Alexander Belopolsky <
alexander.belopol...@gmail.com> wrote:

> On Wed, Jul 19, 2017 at 9:08 PM, Guido van Rossum 
> wrote:
> > The proposal in your email seems incomplete
>
> The proposal does not say anything about type((x=1, y=2)).  I assume
> it will be the same as the type currently returned by namedtuple(?, 'x
> y'), but will these types be cached?


I suppose that the type should be immutable at least as long as field names
are the same, and the cache will occur on creation, in order to retain the
0 memory footprint.

Will type((x=1, y=2)) is type((x=3, y=4)) be True?.


Yes.


> Maybe type((x=1, y=2))(values) will work?
>

It's supposed to behave like a tuple or any other primitive type (list,
set, etc.), so yes.

> Regarding that spec, I think there's something missing: given a list (or
> tuple!) of values, how do you turn it into an 'ntuple'?

As already suggested, it probably makes sense to just reuse the dict syntax:

>>> dict([('a', 1), ('b', 2)])
{'a': 1, 'b': 2}
>>> ntuple([('a', 1), ('b', 2)])
(a=1, b=2)
___
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] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Giampaolo Rodola'
On Tue, Jul 25, 2017 at 9:30 PM, MRAB  wrote:

> On 2017-07-25 19:48, Giampaolo Rodola' wrote:
>
>>
>> On Tue, Jul 25, 2017 at 7:49 PM, MRAB > > wrote:
>>
>> On 2017-07-25 02:57, Nick Coghlan wrote:
>>
>> On 25 July 2017 at 02:46, Michel Desmoulin
>> >
>> wrote:
>>
>> Le 24/07/2017 à 16:12, Nick Coghlan a écrit :
>>
>> On 22 July 2017 at 01:18, Guido van Rossum
>> > wrote:
>>
>> Honestly I would like to declare the bare (x=1,
>> y=0) proposal dead. Let's
>> encourage the use of objects rather than tuples
>> (named or otherwise) for
>> most data exchanges. I know of a large codebase
>> that uses dicts instead of
>> objects, and it's a mess. I expect the bare ntuple
>> to encourage the same
>> chaos.
>>
>>
>> This is the people working on big code base talking.
>>
>>
>> Dedicated syntax:
>>
>>  (x=1, y=0)
>>
>> New builtin:
>>
>>  ntuple(x=1, y=0)
>>
>> So the only thing being ruled out is the dedicated syntax option,
>> since it doesn't let us do anything that a new builtin can't
>> do, it's
>> harder to find help on (as compared to "help(ntuple)" or searching
>> online for "python ntuple"), and it can't be readily backported to
>> Python 3.6 as part of a third party library (you can't easily
>> backport
>> it any further than that regardless, since you'd be missing the
>> order-preservation guarantee for the keyword arguments passed
>> to the
>> builtin).
>>
>> [snip]
>>
>> I think it's a little like function arguments.
>>
>> Arguments can be all positional, but you have to decide in what
>> order they are listed. Named arguments are clearer than positional
>> arguments when calling functions.
>>
>> So an ntuple would be like a tuple, but with names (attributes)
>> instead of positions.
>>
>> I don't see how they could be compatible with tuples because the
>> positions aren't fixed. You would need a NamedTuple where the type
>> specifies the order.
>>
>> I think...
>>
>>
>> Most likely ntuple() will require keyword args only, whereas for
>> collections.namedtuple they are mandatory only during declaration. The
>> order is the same as kwargs, so:
>>
>> >>> nt = ntuple(x=1, y=2)
>> >>> nt[0]
>> 1
>> >>> nt[1]
>> 2
>>
>> What's less clear is how isinstance() should behave. Perhaps:
>>
>> >>> t = (1, 2)
>> >>> nt = ntuple(x=1, y=2)
>> >>> isinstance(nt, tuple)
>> True
>> >>> isinstance(t, ntuple)
>> False
>>
>
> Given:
>
> >>> nt = ntuple(x=1, y=2)
>
> you have nt[0] == 1 because that's the order of the args.
>
> But what about:
>
> >>> nt2 = ntuple(y=2, x=1)
>
> ? Does that mean that nt[0] == 2? Presumably, yes.


> Does nt == nt2?
>
> If it's False, then you've lost some of the advantage of using names
> instead of positions.
>
> It's a little like saying that functions can be called with keyword
> arguments, but the order of those arguments still matters!


Mmmm excellent point. I would expect "nt == nt2" to be True because
collections.namedtuple() final instance works like that (compares pure
values), because at the end of the day it's a tuple subclass and so should
be ntuple() (meaning I expect "isinstance(ntuple(x=1, y=2), tuple)" to be
True).

On the other hand it's also legitimate to expect "nt == nt2" to be False
because field names are different. That would be made clear in the doc, but
the fact that people will have to look it up means it's not obvious.

-- 
Giampaolo - http://grodola.blogspot.com
___
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] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread MRAB

On 2017-07-25 19:48, Giampaolo Rodola' wrote:


On Tue, Jul 25, 2017 at 7:49 PM, MRAB > wrote:


On 2017-07-25 02:57, Nick Coghlan wrote:

On 25 July 2017 at 02:46, Michel Desmoulin
>
wrote:

Le 24/07/2017 à 16:12, Nick Coghlan a écrit :

On 22 July 2017 at 01:18, Guido van Rossum
> wrote:

Honestly I would like to declare the bare (x=1,
y=0) proposal dead. Let's
encourage the use of objects rather than tuples
(named or otherwise) for
most data exchanges. I know of a large codebase
that uses dicts instead of
objects, and it's a mess. I expect the bare ntuple
to encourage the same
chaos.


This is the people working on big code base talking.


Dedicated syntax:

 (x=1, y=0)

New builtin:

 ntuple(x=1, y=0)

So the only thing being ruled out is the dedicated syntax option,
since it doesn't let us do anything that a new builtin can't
do, it's
harder to find help on (as compared to "help(ntuple)" or searching
online for "python ntuple"), and it can't be readily backported to
Python 3.6 as part of a third party library (you can't easily
backport
it any further than that regardless, since you'd be missing the
order-preservation guarantee for the keyword arguments passed
to the
builtin).

[snip]

I think it's a little like function arguments.

Arguments can be all positional, but you have to decide in what
order they are listed. Named arguments are clearer than positional
arguments when calling functions.

So an ntuple would be like a tuple, but with names (attributes)
instead of positions.

I don't see how they could be compatible with tuples because the
positions aren't fixed. You would need a NamedTuple where the type
specifies the order.

I think...


Most likely ntuple() will require keyword args only, whereas for 
collections.namedtuple they are mandatory only during declaration. The 
order is the same as kwargs, so:


>>> nt = ntuple(x=1, y=2)
>>> nt[0]
1
>>> nt[1]
2

What's less clear is how isinstance() should behave. Perhaps:

>>> t = (1, 2)
>>> nt = ntuple(x=1, y=2)
>>> isinstance(nt, tuple)
True
>>> isinstance(t, ntuple)
False


Given:

>>> nt = ntuple(x=1, y=2)

you have nt[0] == 1 because that's the order of the args.

But what about:

>>> nt2 = ntuple(y=2, x=1)

? Does that mean that nt[0] == 2? Presumably, yes.

Does nt == nt2?

If it's False, then you've lost some of the advantage of using names 
instead of positions.


It's a little like saying that functions can be called with keyword 
arguments, but the order of those arguments still matters!


___
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] Idea : for smarter assignment?

2017-07-25 Thread Pavol Lisy
On 7/25/17, MRAB  wrote:
> On 2017-07-25 18:02, Nick Timkovich wrote:
>> On Fri, Jul 21, 2017 at 12:59 PM, David Mertz > > wrote:
>>
>> But you've left out quite a few binding operations.  I might forget
>> some, but here are several:
>>
>>
>> Ned Batchelder had a good presentation at PyCon 2015 about
>> names/values/assignments/binding: https://youtu.be/_AEJHKGk9ns?t=12m52s
>> His summary of all assignment operators:
>>
>> X = ...
>> for X in ...
>> class X: pass
>> def X: pass
>> def fn(X): # when called, X is bound
>> import X
>> from ... import X
>> except ... as X:
>> with ... as X:
>>
> There's also:
>
> import ... as X
> from ... import ... as X

globals()['X'] = ...
___
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] Idea : for smarter assignment?

2017-07-25 Thread MRAB

On 2017-07-25 18:02, Nick Timkovich wrote:
On Fri, Jul 21, 2017 at 12:59 PM, David Mertz > wrote:


But you've left out quite a few binding operations.  I might forget
some, but here are several:


Ned Batchelder had a good presentation at PyCon 2015 about 
names/values/assignments/binding: https://youtu.be/_AEJHKGk9ns?t=12m52s 
His summary of all assignment operators:


X = ...
for X in ...
class X: pass
def X: pass
def fn(X): # when called, X is bound
import X
from ... import X
except ... as X:
with ... as X:


There's also:

import ... as X
from ... import ... as X

...I think only includes one other assignment type from what you listed 
(function parameters) that ironically is where one could maybe blur =/:, 
as doing f(x=3) and f(**{x: 3}) are usually similar (I think some C 
functions react poorly?).



___
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] Idea : for smarter assignment?

2017-07-25 Thread Chris Angelico
On Wed, Jul 26, 2017 at 3:02 AM, Nick Timkovich  wrote:
> ...I think only includes one other assignment type from what you listed
> (function parameters) that ironically is where one could maybe blur =/:, as
> doing f(x=3) and f(**{x: 3}) are usually similar (I think some C functions
> react poorly?).

The only difference with C functions is that you can have named
positional-only parameters, which you can't do in a pure-Python
function. The nearest equivalent is to use *args and then peel the
arguments off that manually, but then they don't have names at all.

ChrisA
___
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] Idea : for smarter assignment?

2017-07-25 Thread Nick Timkovich
On Fri, Jul 21, 2017 at 12:59 PM, David Mertz  wrote:
>
> But you've left out quite a few binding operations.  I might forget some,
> but here are several:
>

Ned Batchelder had a good presentation at PyCon 2015 about
names/values/assignments/binding: https://youtu.be/_AEJHKGk9ns?t=12m52s His
summary of all assignment operators:

X = ...
for X in ...
class X: pass
def X: pass
def fn(X): # when called, X is bound
import X
from ... import X
except ... as X:
with ... as X:

...I think only includes one other assignment type from what you listed
(function parameters) that ironically is where one could maybe blur =/:, as
doing f(x=3) and f(**{x: 3}) are usually similar (I think some C functions
react poorly?).
___
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] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Juancarlo Añez
Steven,

(short of time here)

With **kwargs and a little more work, the function would check if the type
is already defined, and retur the ntuple with the correct type, not the
type.

Your sketch of a solution convinced me it can be done with a library
function; no additional syntax needed.

Cheers,

On Tue, Jul 25, 2017 at 5:08 AM, Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> C Anthony Risinger writes:
>
>  > At the end of the day, I don't see a way to have both a literal and
>  > something that is externally "named", because the only ways to pass the
>  > name I can imagine would make it look like a value within the container
>  > itself (such as using a literal string for the first item), unless even
>  > more new syntax was added.
>
> OK, so I took your "a tuple is a tuple is a tuple" incorrectly.  What
> you want (as I understand it now) is not what
>
> def ntuple0(attr_list):
> return namedtuple("_", attr_list)
>
> gives you, but something like what
>
> def ntuple1(attr_list)
> return namedtuple("ImplicitNamedtuple_" + "_".join(attr_list),
>   attr_list)
>
> does.  Then this would truly be a "duck-typed namedtuple" as Chris
> Barker proposed in response to Steven d'Aprano elsewhere in this
> thread.  See also Nick's full, namedtuple-compatible, implementation.
> Of course we still have the horrible "list of strings naming
> attributes" argument, so you still want a literal if possible, but
> with a **key argument, a new builtin would do the trick for me.  YMMV.
>
>
> --
> Associate Professor  Division of Policy and Planning Science
> http://turnbull/sk.tsukuba.ac.jp/ Faculty of Systems and Information
> Email: turnb...@sk.tsukuba.ac.jp   University of Tsukuba
> Tel: 029-853-5175 Tennodai 1-1-1, Tsukuba 305-8573 JAPAN
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
Juancarlo *Añez*
___
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] namedtuple literals [Was: RE a new namedtuple]

2017-07-25 Thread Stephen J. Turnbull
C Anthony Risinger writes:

 > At the end of the day, I don't see a way to have both a literal and
 > something that is externally "named", because the only ways to pass the
 > name I can imagine would make it look like a value within the container
 > itself (such as using a literal string for the first item), unless even
 > more new syntax was added.

OK, so I took your "a tuple is a tuple is a tuple" incorrectly.  What
you want (as I understand it now) is not what

def ntuple0(attr_list):
return namedtuple("_", attr_list)

gives you, but something like what

def ntuple1(attr_list)
return namedtuple("ImplicitNamedtuple_" + "_".join(attr_list),
  attr_list)

does.  Then this would truly be a "duck-typed namedtuple" as Chris
Barker proposed in response to Steven d'Aprano elsewhere in this
thread.  See also Nick's full, namedtuple-compatible, implementation.
Of course we still have the horrible "list of strings naming
attributes" argument, so you still want a literal if possible, but
with a **key argument, a new builtin would do the trick for me.  YMMV.


-- 
Associate Professor  Division of Policy and Planning Science
http://turnbull/sk.tsukuba.ac.jp/ Faculty of Systems and Information
Email: turnb...@sk.tsukuba.ac.jp   University of Tsukuba
Tel: 029-853-5175 Tennodai 1-1-1, Tsukuba 305-8573 JAPAN
___
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] namedtuple redesign goals

2017-07-25 Thread Stephen J. Turnbull
Michel Desmoulin writes:

 > You are assuming a namedtuple litteral would mean
 > collections.namedtuple would lose the type hability. It's not the
 > case. The litterals can be complement, not a remplacement.

Unlikely to fly in Python.  We really don't like things that have
"obvious semantics" based on appearance that don't have those
semantics.  Something like "(x=0, y=1)" is so obviously a literal
creating a collections.namedtuple, the object it creates really needs
to *be* a collections.namedtuple.

YMMV, but I suspect most Python developers will agree with me to some
extent, and most of those, pretty strongly.

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/