Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #39082 > unrolled thread
| Started by | John Reid <johnbaronreid@gmail.com> |
|---|---|
| First post | 2013-02-18 03:47 -0800 |
| Last post | 2013-02-19 09:36 +0000 |
| Articles | 20 on this page of 33 — 11 participants |
Back to article view | Back to comp.lang.python
Differences creating tuples and collections.namedtuples John Reid <johnbaronreid@gmail.com> - 2013-02-18 03:47 -0800
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-18 12:03 +0000
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-18 12:05 +0000
Re: Differences creating tuples and collections.namedtuples Dave Angel <davea@davea.name> - 2013-02-18 07:11 -0500
Re: Differences creating tuples and collections.namedtuples John Reid <johnbaronreid@gmail.com> - 2013-02-18 13:49 +0000
Re: Differences creating tuples and collections.namedtuples John Reid <johnbaronreid@gmail.com> - 2013-02-18 13:51 +0000
Re: Differences creating tuples and collections.namedtuples John Reid <j.reid@mail.cryst.bbk.ac.uk> - 2013-02-18 14:09 +0000
Re: Differences creating tuples and collections.namedtuples raymond.hettinger@gmail.com - 2013-02-18 23:48 -0800
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 08:06 +0000
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 08:57 +0000
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 08:06 +0000
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 08:05 +0000
Re: Differences creating tuples and collections.namedtuples raymond.hettinger@gmail.com - 2013-02-18 23:48 -0800
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-18 14:15 +0000
Re: Differences creating tuples and collections.namedtuples John Reid <johnbaronreid@gmail.com> - 2013-02-18 14:18 +0000
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-18 14:12 +0000
Re: Differences creating tuples and collections.namedtuples John Reid <j.reid@mail.cryst.bbk.ac.uk> - 2013-02-18 14:23 +0000
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-18 14:53 +0000
Re: Differences creating tuples and collections.namedtuples John Reid <j.reid@mail.cryst.bbk.ac.uk> - 2013-02-18 15:07 +0000
Re: Differences creating tuples and collections.namedtuples Terry Reedy <tjreedy@udel.edu> - 2013-02-18 16:28 -0500
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 11:18 +1100
Re: Differences creating tuples and collections.namedtuples Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-02-19 01:43 +0000
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-19 14:06 +1100
Re: Differences creating tuples and collections.namedtuples Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2013-02-19 21:27 +1300
Re: Differences creating tuples and collections.namedtuples Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2013-02-19 20:54 +1300
Re: Differences creating tuples and collections.namedtuples John Reid <j.reid@mail.cryst.bbk.ac.uk> - 2013-02-19 09:30 +0000
Re: Differences creating tuples and collections.namedtuples Terry Reedy <tjreedy@udel.edu> - 2013-02-19 22:38 -0500
Re: Differences creating tuples and collections.namedtuples Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-22 10:38 +0000
Re: Differences creating tuples and collections.namedtuples Chris Angelico <rosuav@gmail.com> - 2013-02-20 17:50 +1100
Re: Differences creating tuples and collections.namedtuples Roy Smith <roy@panix.com> - 2013-02-20 09:09 -0500
Re: Differences creating tuples and collections.namedtuples Roy Smith <roy@panix.com> - 2013-02-18 20:11 -0500
Re: Differences creating tuples and collections.namedtuples alex23 <wuwei23@gmail.com> - 2013-02-18 17:47 -0800
Re: Differences creating tuples and collections.namedtuples John Reid <j.reid@mail.cryst.bbk.ac.uk> - 2013-02-19 09:36 +0000
Page 1 of 2 [1] 2 Next page →
| From | John Reid <johnbaronreid@gmail.com> |
|---|---|
| Date | 2013-02-18 03:47 -0800 |
| Subject | Differences creating tuples and collections.namedtuples |
| Message-ID | <7a40a426-baa9-46f8-8f9d-59ba32b044f3@googlegroups.com> |
Hi,
I was hoping namedtuples could be used as replacements for tuples in all instances. There seem to be some differences between how tuples and namedtuples are created. For example with a tuple I can do:
a=tuple([1,2,3])
with namedtuples I get a TypeError:
from collections import namedtuple
B=namedtuple('B', 'x y z')
b=B([1,2,3])
TypeError: __new__() takes exactly 4 arguments (2 given)
> <ipython-input-23-d1da2ef851fb>(3)<module>()
1 from collections import namedtuple
2 B=namedtuple('B', 'x y z')
----> 3 b=B([1,2,3])
I'm seeing this problem because of the following code in IPython:
def canSequence(obj):
if isinstance(obj, (list, tuple)):
t = type(obj)
return t([can(i) for i in obj])
else:
return obj
where obj is a namedtuple and t([can(i) for i in obj]) fails with the TypeError. See http://article.gmane.org/gmane.comp.python.ipython.user/10270 for more info.
Is this a problem with namedtuples, ipython or just a feature?
Thanks,
John.
[toc] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-02-18 12:03 +0000 |
| Message-ID | <mailman.1934.1361189017.2939.python-list@python.org> |
| In reply to | #39082 |
On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote:
> Hi,
>
> I was hoping namedtuples could be used as replacements for tuples in all instances.
namedtuples are not really intended to serves as tuples anywhere. They
are intended to provide lightweight, immutable, hashable objects with
*named* (rather than numbered) values.
> There seem to be some differences between how tuples and namedtuples are created. For example with a tuple I can do:
>
> a=tuple([1,2,3])
>
> with namedtuples I get a TypeError:
>
> from collections import namedtuple
> B=namedtuple('B', 'x y z')
> b=B([1,2,3])
For a namedtuple you need to unpack the arguments
b = B(*[1, 2, 3])
or
b = B(1, 2, 3)
>
> TypeError: __new__() takes exactly 4 arguments (2 given)
>> <ipython-input-23-d1da2ef851fb>(3)<module>()
> 1 from collections import namedtuple
> 2 B=namedtuple('B', 'x y z')
> ----> 3 b=B([1,2,3])
>
> I'm seeing this problem because of the following code in IPython:
>
> def canSequence(obj):
> if isinstance(obj, (list, tuple)):
> t = type(obj)
> return t([can(i) for i in obj])
> else:
> return obj
What is the point of the code above? If obj is a list or a tuple you
create a new list or tuple with the same data and then return it
otherwise you just return the object. What about:
def canSequence(obj):
return obj
Or is it that you want to copy the object (but only when it is a tuple
or list). Then how about
def canSequence(obj):
if isinstance(obj, (list, tuple)):
return obj[:]
else:
return obj
Note that this turns namedtuples into tuples. It might be better to
catch TypeError rather than special casing the types:
def canSequence(obj):
try:
return obj[:]
except TypeError:
return obj
Or perhaps it would be better to use the copy module (assuming that
the purpose is to copy the object).
>
> where obj is a namedtuple and t([can(i) for i in obj]) fails with the TypeError. See http://article.gmane.org/gmane.comp.python.ipython.user/10270 for more info.
>
> Is this a problem with namedtuples, ipython or just a feature?
I think that it is a problem with the canSequence function.
Oscar
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-02-18 12:05 +0000 |
| Message-ID | <mailman.1935.1361189141.2939.python-list@python.org> |
| In reply to | #39082 |
On 18 February 2013 12:03, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote: > On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote: >> I'm seeing this problem because of the following code in IPython: >> >> def canSequence(obj): >> if isinstance(obj, (list, tuple)): >> t = type(obj) >> return t([can(i) for i in obj]) >> else: >> return obj > > What is the point of the code above? If obj is a list or a tuple you > create a new list or tuple with the same data and then return it > otherwise you just return the object. What about: Sorry, I didn't read this properly. I see that you want apply can() to all the elements. What is the reason for wanting to preserve the type of the sequence? Oscar
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <davea@davea.name> |
|---|---|
| Date | 2013-02-18 07:11 -0500 |
| Message-ID | <mailman.1936.1361189497.2939.python-list@python.org> |
| In reply to | #39082 |
On 02/18/2013 06:47 AM, John Reid wrote:
> Hi,
>
> I was hoping namedtuples could be used as replacements for tuples in all instances. There seem to be some differences between how tuples and namedtuples are created. For example with a tuple I can do:
>
> a=tuple([1,2,3])
>
> with namedtuples I get a TypeError:
>
> from collections import namedtuple
> B=namedtuple('B', 'x y z')
> b=B([1,2,3])
You are passing a single list to the constructor, but you specified that
the namedtuple was to have 3 items. So you need two more.
>
> TypeError: __new__() takes exactly 4 arguments (2 given)
>> <ipython-input-23-d1da2ef851fb>(3)<module>()
> 1 from collections import namedtuple
> 2 B=namedtuple('B', 'x y z')
> ----> 3 b=B([1,2,3])
>
> I'm seeing this problem because of the following code in IPython:
>
> def canSequence(obj):
> if isinstance(obj, (list, tuple)):
> t = type(obj)
> return t([can(i) for i in obj])
> else:
> return obj
>
> where obj is a namedtuple and t([can(i) for i in obj]) fails with the TypeError. See http://article.gmane.org/gmane.comp.python.ipython.user/10270 for more info.
>
> Is this a problem with namedtuples, ipython or just a feature?
>
> Thanks,
> John.
>
If you want one item (list or tuple) to act like 3 separate arguments,
you could use the "*" operator:
b = B( *[1,2,3] )
or in your canSequence function, if you want a namedTuple
return t(*[can(i) for i in obj])
--
DaveA
[toc] | [prev] | [next] | [standalone]
| From | John Reid <johnbaronreid@gmail.com> |
|---|---|
| Date | 2013-02-18 13:49 +0000 |
| Message-ID | <mailman.1939.1361195360.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 12:05, Oscar Benjamin wrote: > On 18 February 2013 12:03, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote: >> On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote: >>> I'm seeing this problem because of the following code in IPython: >>> >>> def canSequence(obj): >>> if isinstance(obj, (list, tuple)): >>> t = type(obj) >>> return t([can(i) for i in obj]) >>> else: >>> return obj >> What is the point of the code above? If obj is a list or a tuple you >> create a new list or tuple with the same data and then return it >> otherwise you just return the object. What about: > Sorry, I didn't read this properly. I see that you want apply can() to > all the elements. What is the reason for wanting to preserve the type > of the sequence? > > Well like I said it is not me that wants to do this. It is part of the code in IPython for sending messages between clients and engines.
[toc] | [prev] | [next] | [standalone]
| From | John Reid <johnbaronreid@gmail.com> |
|---|---|
| Date | 2013-02-18 13:51 +0000 |
| Message-ID | <mailman.1940.1361196430.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 12:03, Oscar Benjamin wrote: > On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote: >> Hi, >> >> I was hoping namedtuples could be used as replacements for tuples in all instances. > namedtuples are not really intended to serves as tuples anywhere. They > are intended to provide lightweight, immutable, hashable objects with > *named* (rather than numbered) values. If they are not supposed to be tuples then calling them namedtuples and inheriting from tuple seems a little odd.
[toc] | [prev] | [next] | [standalone]
| From | John Reid <j.reid@mail.cryst.bbk.ac.uk> |
|---|---|
| Date | 2013-02-18 14:09 +0000 |
| Message-ID | <mailman.1942.1361196573.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 12:11, Dave Angel wrote:
> On 02/18/2013 06:47 AM, John Reid wrote:
>> Hi,
>>
>> I was hoping namedtuples could be used as replacements for tuples in
>> all instances. There seem to be some differences between how tuples
>> and namedtuples are created. For example with a tuple I can do:
>>
>> a=tuple([1,2,3])
>>
>> with namedtuples I get a TypeError:
>>
>> from collections import namedtuple
>> B=namedtuple('B', 'x y z')
>> b=B([1,2,3])
>
> You are passing a single list to the constructor, but you specified that
> the namedtuple was to have 3 items. So you need two more.
I'm aware how to construct the namedtuple and the tuple. My point was
that they use different syntaxes for the same operation and this seems
to break ipython. I was wondering if this is a necessary design feature
or perhaps just an oversight on the part of the namedtuple author or
ipython developers.
[toc] | [prev] | [next] | [standalone]
| From | raymond.hettinger@gmail.com |
|---|---|
| Date | 2013-02-18 23:48 -0800 |
| Message-ID | <cdf1f2f4-98e8-4456-9b48-ab6fb3aef845@googlegroups.com> |
| In reply to | #39092 |
On Monday, February 18, 2013 6:09:16 AM UTC-8, John Reid wrote:
> I'm aware how to construct the namedtuple and the tuple. My point was
> that they use different syntaxes for the same operation and this seems
> to break ipython. I was wondering if this is a necessary design feature
> or perhaps just an oversight on the part of the namedtuple author or
> ipython developers.
It was not an oversight on the part of the namedtuple author.
It was a deliberate design decision to improve usability for
named tuple's primary use case.
Consider a namedtuple such as:
Person = namedtuple('Person', ['name', 'rank', 'serial_number'])
With the current signature, instances can be created like this:
p = Person('Guido', 'BDFL', 1)
If instead, the __new__ signature matched that of regular tuples,
you would need to write:
p = Person(('Guido', 'BDFL', 1))
The double parens are awkward. You would lose tooltips that prompt you for Person(name, rank, serial_number). You would lose the ability to use keyword arguments such as Person(rank='BDFL', serial_number=1, name='Guido') or Person(**d). The repr for the namedtuple would lose its eval(repr(t)) roundtrip property.
If your starting point is an existing iterable such as s=['Guido', 'BDFL', 1], you have a couple of choices: p=Person(*s) or p=Person._make(s). The latter form was put it to help avoid unpacking and repacking the arguments.
Raymond
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-02-19 08:06 +0000 |
| Message-ID | <512332a1$0$29881$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #39188 |
On Mon, 18 Feb 2013 23:48:46 -0800, raymond.hettinger wrote: [...] > If your starting point is an existing iterable such as s=['Guido', > 'BDFL', 1], you have a couple of choices: p=Person(*s) or > p=Person._make(s). The latter form was put it to help avoid unpacking > and repacking the arguments. It might not be obvious to the casual reader, but despite the leading underscore, _make is part of the public API for namedtuple: http://docs.python.org/2/library/collections.html#collections.namedtuple -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-02-19 08:57 +0000 |
| Message-ID | <51233e75$0$21906$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #39188 |
Pardon me for the double-post, if any, my news client appears to have eaten my first reply. On Mon, 18 Feb 2013 23:48:46 -0800, raymond.hettinger wrote: [...] > If your starting point is an existing iterable such as s=['Guido', > 'BDFL', 1], you have a couple of choices: p=Person(*s) or > p=Person._make(s). The latter form was put it to help avoid unpacking > and repacking the arguments. It might not be obvious to the casual reader, but despite the leading underscore, _make is part of the public API for namedtuple: http://docs.python.org/2/library/collections.html#collections.namedtuple -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-02-19 08:06 +0000 |
| Message-ID | <51233282$0$21921$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #39188 |
On Mon, 18 Feb 2013 23:48:46 -0800, raymond.hettinger wrote: [...] > If your starting point is an existing iterable such as s=['Guido', > 'BDFL', 1], you have a couple of choices: p=Person(*s) or > p=Person._make(s). The latter form was put it to help avoid unpacking > and repacking the arguments. It might not be obvious to the casual reader, but despite the leading underscore, _make is part of the public API for namedtuple: http://docs.python.org/2/library/collections.html#collections.namedtuple -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-02-19 08:05 +0000 |
| Message-ID | <51233263$0$21762$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #39188 |
On Mon, 18 Feb 2013 23:48:46 -0800, raymond.hettinger wrote: [...] > If your starting point is an existing iterable such as s=['Guido', > 'BDFL', 1], you have a couple of choices: p=Person(*s) or > p=Person._make(s). The latter form was put it to help avoid unpacking > and repacking the arguments. It might not be obvious to the casual reader, but despite the leading underscore, _make is part of the public API for namedtuple: http://docs.python.org/2/library/collections.html#collections.namedtuple -- Steven
[toc] | [prev] | [next] | [standalone]
| From | raymond.hettinger@gmail.com |
|---|---|
| Date | 2013-02-18 23:48 -0800 |
| Message-ID | <mailman.2007.1361260822.2939.python-list@python.org> |
| In reply to | #39092 |
On Monday, February 18, 2013 6:09:16 AM UTC-8, John Reid wrote:
> I'm aware how to construct the namedtuple and the tuple. My point was
> that they use different syntaxes for the same operation and this seems
> to break ipython. I was wondering if this is a necessary design feature
> or perhaps just an oversight on the part of the namedtuple author or
> ipython developers.
It was not an oversight on the part of the namedtuple author.
It was a deliberate design decision to improve usability for
named tuple's primary use case.
Consider a namedtuple such as:
Person = namedtuple('Person', ['name', 'rank', 'serial_number'])
With the current signature, instances can be created like this:
p = Person('Guido', 'BDFL', 1)
If instead, the __new__ signature matched that of regular tuples,
you would need to write:
p = Person(('Guido', 'BDFL', 1))
The double parens are awkward. You would lose tooltips that prompt you for Person(name, rank, serial_number). You would lose the ability to use keyword arguments such as Person(rank='BDFL', serial_number=1, name='Guido') or Person(**d). The repr for the namedtuple would lose its eval(repr(t)) roundtrip property.
If your starting point is an existing iterable such as s=['Guido', 'BDFL', 1], you have a couple of choices: p=Person(*s) or p=Person._make(s). The latter form was put it to help avoid unpacking and repacking the arguments.
Raymond
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-02-18 14:15 +0000 |
| Message-ID | <mailman.1943.1361196973.2939.python-list@python.org> |
| In reply to | #39082 |
On 18 February 2013 14:09, John Reid <j.reid@mail.cryst.bbk.ac.uk> wrote:
> On 18/02/13 12:11, Dave Angel wrote:
>> On 02/18/2013 06:47 AM, John Reid wrote:
>>> Hi,
>>>
>>> I was hoping namedtuples could be used as replacements for tuples in
>>> all instances. There seem to be some differences between how tuples
>>> and namedtuples are created. For example with a tuple I can do:
>>>
>>> a=tuple([1,2,3])
>>>
>>> with namedtuples I get a TypeError:
>>>
>>> from collections import namedtuple
>>> B=namedtuple('B', 'x y z')
>>> b=B([1,2,3])
>>
>> You are passing a single list to the constructor, but you specified that
>> the namedtuple was to have 3 items. So you need two more.
>
> I'm aware how to construct the namedtuple and the tuple. My point was
> that they use different syntaxes for the same operation and this seems
> to break ipython. I was wondering if this is a necessary design feature
> or perhaps just an oversight on the part of the namedtuple author or
> ipython developers.
I would say that depending on isinstance(obj, tuple) was the error. I
can't offer a suggestion as you haven't clarified what the purpose of
this code in canSequence() is or what constraints it is expected to
satisfy.
Oscar
[toc] | [prev] | [next] | [standalone]
| From | John Reid <johnbaronreid@gmail.com> |
|---|---|
| Date | 2013-02-18 14:18 +0000 |
| Message-ID | <mailman.1944.1361197131.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 14:12, Oscar Benjamin wrote: > On 18 February 2013 13:51, John Reid <johnbaronreid@gmail.com> wrote: >> On 18/02/13 12:03, Oscar Benjamin wrote: >>> On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote: >>>> Hi, >>>> >>>> I was hoping namedtuples could be used as replacements for tuples in all instances. >>> namedtuples are not really intended to serves as tuples anywhere. They >>> are intended to provide lightweight, immutable, hashable objects with >>> *named* (rather than numbered) values. >> If they are not supposed to be tuples then calling them namedtuples and >> inheriting from tuple seems a little odd. > You can use namedtuple instances in places that expect tuples. > Inheriting from tuples enables them to be all the things I said: > lightweight, immutable and hashable. The type object itself has a > different interface for the constructor, though. > > Then I can't use them in every place I use tuples. For example IPython relies upon the type's interface for the constructor as part of a serialization mechanism. I wonder why they have a different interface. It seems to restrict their usability. No doubt there were other factors involved in the design of the interface. John.
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-02-18 14:12 +0000 |
| Message-ID | <mailman.1945.1361197214.2939.python-list@python.org> |
| In reply to | #39082 |
On 18 February 2013 13:51, John Reid <johnbaronreid@gmail.com> wrote: > On 18/02/13 12:03, Oscar Benjamin wrote: >> On 18 February 2013 11:47, John Reid <johnbaronreid@gmail.com> wrote: >>> Hi, >>> >>> I was hoping namedtuples could be used as replacements for tuples in all instances. >> namedtuples are not really intended to serves as tuples anywhere. They >> are intended to provide lightweight, immutable, hashable objects with >> *named* (rather than numbered) values. > > If they are not supposed to be tuples then calling them namedtuples and > inheriting from tuple seems a little odd. You can use namedtuple instances in places that expect tuples. Inheriting from tuples enables them to be all the things I said: lightweight, immutable and hashable. The type object itself has a different interface for the constructor, though. Oscar
[toc] | [prev] | [next] | [standalone]
| From | John Reid <j.reid@mail.cryst.bbk.ac.uk> |
|---|---|
| Date | 2013-02-18 14:23 +0000 |
| Message-ID | <mailman.1946.1361197396.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 14:15, Oscar Benjamin wrote:
> On 18 February 2013 14:09, John Reid <j.reid@mail.cryst.bbk.ac.uk> wrote:
>> On 18/02/13 12:11, Dave Angel wrote:
>>> On 02/18/2013 06:47 AM, John Reid wrote:
>>>> Hi,
>>>>
>>>> I was hoping namedtuples could be used as replacements for tuples in
>>>> all instances. There seem to be some differences between how tuples
>>>> and namedtuples are created. For example with a tuple I can do:
>>>>
>>>> a=tuple([1,2,3])
>>>>
>>>> with namedtuples I get a TypeError:
>>>>
>>>> from collections import namedtuple
>>>> B=namedtuple('B', 'x y z')
>>>> b=B([1,2,3])
>>>
>>> You are passing a single list to the constructor, but you specified that
>>> the namedtuple was to have 3 items. So you need two more.
>>
>> I'm aware how to construct the namedtuple and the tuple. My point was
>> that they use different syntaxes for the same operation and this seems
>> to break ipython. I was wondering if this is a necessary design feature
>> or perhaps just an oversight on the part of the namedtuple author or
>> ipython developers.
>
> I would say that depending on isinstance(obj, tuple) was the error. I
> can't offer a suggestion as you haven't clarified what the purpose of
> this code in canSequence() is or what constraints it is expected to
> satisfy.
>
Like I said it is not my code. I'm hoping the IPython developers can
help me out here. That said it would be nice to know the rationale for
namedtuple.__new__ to have a different signature to tuple.__new__. I'm
guessing namedtuple._make has a similar interface to tuple.__new__. Does
anyone know what the rationale was for this design?
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-02-18 14:53 +0000 |
| Message-ID | <mailman.1949.1361199242.2939.python-list@python.org> |
| In reply to | #39082 |
On 18 February 2013 14:23, John Reid <j.reid@mail.cryst.bbk.ac.uk> wrote:
[snip]
> That said it would be nice to know the rationale for
> namedtuple.__new__ to have a different signature to tuple.__new__. I'm
> guessing namedtuple._make has a similar interface to tuple.__new__. Does
> anyone know what the rationale was for this design?
Because namedtuples use names for the arguments in the constructor:
>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x y')
>>> p1 = Point(x=2, y=3)
>>> p1
Point(x=2, y=3)
>>> p1.x
2
Oscar
[toc] | [prev] | [next] | [standalone]
| From | John Reid <j.reid@mail.cryst.bbk.ac.uk> |
|---|---|
| Date | 2013-02-18 15:07 +0000 |
| Message-ID | <mailman.1951.1361200036.2939.python-list@python.org> |
| In reply to | #39082 |
On 18/02/13 14:53, Oscar Benjamin wrote:
> On 18 February 2013 14:23, John Reid <j.reid@mail.cryst.bbk.ac.uk> wrote:
> [snip]
>> That said it would be nice to know the rationale for
>> namedtuple.__new__ to have a different signature to tuple.__new__. I'm
>> guessing namedtuple._make has a similar interface to tuple.__new__. Does
>> anyone know what the rationale was for this design?
>
> Because namedtuples use names for the arguments in the constructor:
>
>>>> from collections import namedtuple
>>>> Point = namedtuple('Point', 'x y')
>>>> p1 = Point(x=2, y=3)
>>>> p1
> Point(x=2, y=3)
>>>> p1.x
> 2
>
That's a good point. I haven't used __new__ much before but wouldn't
something like this __new__() cater for both uses? (Example taken from
namedtuple docs
http://docs.python.org/2/library/collections.html#collections.namedtuple).
>>> Point = namedtuple('Point', ['x', 'y'], verbose=True)
class Point(tuple):
'Point(x, y)'
__slots__ = ()
_fields = ('x', 'y')
def __new__(_cls, *args, **kwds):
'Create a new instance of Point(x, y)'
if args:
return _tuple.__new__(_cls, args)
else:
return _tuple.__new__(_cls, (kwds[f] for f in _fields))
...
Perhaps I could subclass namedtuple so that my namedtuples have the
correct signature for __new__.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2013-02-18 16:28 -0500 |
| Message-ID | <mailman.1972.1361222953.2939.python-list@python.org> |
| In reply to | #39082 |
On 2/18/2013 6:47 AM, John Reid wrote:
> I was hoping namedtuples could be used as replacements for tuples
> in all instances.
This is a mistake in the following two senses. First, tuple is a class
with instances while namedtuple is a class factory that produces
classes. (One could think of namedtuple as a metaclass, but it was not
implemented that way.) Second, a tuple instance can have any length and
different instances can have different lengths. On the other hand, all
instances of a particular namedtuple class have a fixed length. This
affects their initialization. So does the fact that Oscar mentioned,
that fields can be initialized by name.
> There seem to be some differences between how tuples and namedtuples
> are created. For example with a tuple I can do:
>
> a=tuple([1,2,3])
But no sensible person would ever do that, since it creates an
unnecessary list and is equivalent to
a = 1,2,3
The actual api is tuple(iterable). I presume you know that, but it gets
to the question you ask about 'why the difference?'. The only reason to
use an explicit tuple() call is when you already have an iterable,
possibly of unknown length, rather than the individual field objects. In
the latter case, one should use a display.
> with namedtuples I get a TypeError:
>
> from collections import namedtuple
> B=namedtuple('B', 'x y z')
> b=B([1,2,3])
There is no namedtuple B display, so one *must* use an explicit call
with the proper number of args. The simplest possibility is B(val0,
val1, val2). Initializaing a namedtuple from an iterable is unusual, and
hence gets the longer syntax. In other words, the typical use case for a
namedtuple class is to replace statements that have tuple display.
return a, b, c
to
return B(a, b, c)
or
x = a, b, c
to
x = B(a, b, c)
It is much less common to change tuple(iterable) to B(iterable).
> def canSequence(obj):
> if isinstance(obj, (list, tuple)):
> t = type(obj)
> return t([can(i) for i in obj])
> else:
> return obj
The first return could also be written t(map(can, obj)) or, in Python 3,
t(can(i) for i in obj).
> where obj is a namedtuple and t([can(i) for i in obj]) fails with the TypeError. See http://article.gmane.org/gmane.comp.python.ipython.user/10270 for more info.
>
> Is this a problem with namedtuples, ipython or just a feature?
With canSequence. If isinstance was available and the above were written
before list and tuple could be subclassed, canSequence was sensible when
written. But as Oscar said, it is now a mistake for canSequence to
assume that all subclasses of list and tuple have the same
initialization api.
In fact, one reason to subclass a class is to change the initialization
api. For instance, before python 3, range was a function that returned a
list. If lists had always been able to be subclasses, it might instead
have been written as a list subclass that attached the start, stop, and
step values, like so:
# python 3
class rangelist(list):
def __init__(self, *args):
r = range(*args)
self.extend(r)
self.start = r.start
self.stop = r.stop
self.step = r.step
r10 = rangelist(10)
print(r10, r10.start, r10.stop, r10.step)
>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0 10 1
However, define can() and canSequence(r10) will raise a TypeError, just
as with a namedtuple B instance.
TypeError: 'list' object cannot be interpreted as an integer
So, while your question about the namedtuple api is a legitimate one,
your problem with canSequence is not really about namedtuples, but about
canSequence making a bad assumption.
--
Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web