"index" method only for mutable sequences??

C

Carsten Haese

Do you not see the gratuituous inconsistency between tuples and lists
as a useless feature? What is the use case for keeping it?

When a new feature is requested, the burden of proof is on the requester
to show that it has uses. The use case for not having tuple.index is
that there are no use cases for having it. If that answer sounds absurd,
it is because your question is absurd.

-Carsten
 
P

Paul Rubin

Carsten Haese said:
When a new feature is requested, the burden of proof is on the requester
to show that it has uses. The use case for not having tuple.index is
that there are no use cases for having it. If that answer sounds absurd,
it is because your question is absurd.

The use case has already been discussed. Removing the pointless
inconsistency between lists and tuples means you can stop having to
remember it, so you can free up brain cells for implementing useful
things. That increases your programming productivity.
 
B

Bart Willems

James said:
... It boils down to the fact that tuples are useless as a
result unless you know you really need them--and you never really NEED
them.

Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.

So, I *need* those tuples, and they're far from useless to me.

For the rare, rare, rare cases where I *would* need an index function on
a tuple (I've never needed it):

class IndexTuple(tuple):
def index(n):
# your code goes here

would be sufficient, wouldn't it?

Best regards,
Bart
 
C

Carsten Haese

The use case has already been discussed. Removing the pointless
inconsistency between lists and tuples means you can stop having to
remember it, so you can free up brain cells for implementing useful
things. That increases your programming productivity.

Will tuples also get a sort method? What about append and extend? pop?
__iadd__? __delslice__?

How many brain cells are actually freed up by not having to remember
that *one* method that you'd never use doesn't exist?

-Carsten
 
P

Paul Rubin

Carsten Haese said:
Will tuples also get a sort method? What about append and extend? pop?
__iadd__? __delslice__?

They are immutable so they won't get .sort() etc. sorted(...) already
works on them.
How many brain cells are actually freed up by not having to remember
that *one* method that you'd never use doesn't exist?

I dunno but I do know that Ruby is attracting a lot of potential Python
users because it apparently has fewer of these inconsistencies. A big
web site I hang out on decided to do a software rewrite (currently using
a huge perl script) and evaluated a bunch of possible approaches. In
the final decision, Ruby/Rails won out over Python/Django.
 
S

Steven D'Aprano

Will tuples also get a sort method? What about append and extend? pop?
__iadd__? __delslice__?

Since tuples are immutable, no.

And before you ask, since they aren't strings, they won't get upper,
lower, split or strip either.

How many brain cells are actually freed up by not having to remember
that *one* method that you'd never use doesn't exist?

74,972,561.


I think the problem is that Python developers are split between those who
see tuples as immutable lists, and those who see them as records/structs.
Neither of them is wrong -- tuples are multi-use. Guido may or may not
have designed them to be used as structs (short and heterogeneous, as
opposed to long and homogeneous) but designers are often surprised by the
uses people find for their creations, and the designer doesn't get the
final say as to what is the "right" usage.

If you see tuples as an immutable list, having an index method is quite
useful. If you see them as structs, an index method is useless.
 
P

Paul Rubin

Steven D'Aprano said:
I think the problem is that Python developers are split between those who
see tuples as immutable lists, and those who see them as records/structs.

I think the construction

def f(*a): ...

shows that the "immutable list" interpretation is firmly ensconced in
the language.
 
J

James Stroud

Bart said:
Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.


"Impossible" is a strong word, as is "need" (especially when in all caps).

py> import md5
py> class HashedList(list):
.... def __hash__(self):
.... h = md5.new()
.... for item in self:
.... h.update(str(hash(item)))
.... return int(h.hexdigest(), 16)
....
py> hl = HashedList('bob', 'carol', 'ted')
py> {hl:3}
{['bob', 'carol', 'ted']: 3}

Impossible? I wouldn't even say that this was all that difficult.

James
 
S

Steven D'Aprano

Bart said:
Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.


"Impossible" is a strong word, as is "need" (especially when in all caps).

py> import md5
py> class HashedList(list):
... def __hash__(self):
... h = md5.new()
... for item in self:
... h.update(str(hash(item)))
... return int(h.hexdigest(), 16)
...
py> hl = HashedList('bob', 'carol', 'ted')
py> {hl:3}
{['bob', 'carol', 'ted']: 3}

Impossible? I wouldn't even say that this was all that difficult.

Possible, if by possible you mean "broken".

D = {hl: 3}
D {['bob', 'carol', 'ted']: 3}
hl[0] = 'Bob'
D {['Bob', 'carol', 'ted']: 3}
D.keys()[0] is hl True
D[hl]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ['Bob', 'carol', 'ted']
 
J

James Stroud

Steven said:
Bart said:
James Stroud wrote:
... It boils down to the fact that tuples are useless as a result
unless you know you really need them--and you never really NEED them.
Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.

"Impossible" is a strong word, as is "need" (especially when in all caps).

py> import md5
py> class HashedList(list):
... def __hash__(self):
... h = md5.new()
... for item in self:
... h.update(str(hash(item)))
... return int(h.hexdigest(), 16)
...
py> hl = HashedList('bob', 'carol', 'ted')
py> {hl:3}
{['bob', 'carol', 'ted']: 3}

Impossible? I wouldn't even say that this was all that difficult.

Possible, if by possible you mean "broken".

D = {hl: 3}
D {['bob', 'carol', 'ted']: 3}
hl[0] = 'Bob'
D {['Bob', 'carol', 'ted']: 3}
D.keys()[0] is hl True
D[hl]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ['Bob', 'carol', 'ted']

def __setitem__(self, *args):
raise TypeError, '%s doesn't support item assignment.' %
self.__class__.__name__


Problem fixed. Next?

By the way, this would be analagous to the tedious

class Something(object):
def __init__(self, value):
self._value = value
value = property(lambda: self._value)

just to make sure users don't change the value of value so they don't
"break" the instance.

I don't think Bart is changing the items in his keys anyway--so the
problem which was stated as impossible is still possible. The solution
was not to code to your personal expectations but to show how tuples are
never essential. Any number of solutions could fix the problem you have
invented.

James
 
G

Georg Brandl

Paul said:
They are immutable so they won't get .sort() etc. sorted(...) already
works on them.


I dunno but I do know that Ruby is attracting a lot of potential Python
users because it apparently has fewer of these inconsistencies.

It remains to be proven that it is an inconsistency, rather than a design
decision.
A big
web site I hang out on decided to do a software rewrite (currently using
a huge perl script) and evaluated a bunch of possible approaches. In
the final decision, Ruby/Rails won out over Python/Django.

Given that so many web sites still decide to (re)write in PHP, I don't think
that is much of an argument.

Georg
 
G

Georg Brandl

Paul said:
I think the construction

def f(*a): ...

shows that the "immutable list" interpretation is firmly ensconced in
the language.

IIRC, for this use case of tuples there was a practical reason rather than
an interpretation one. It is also on the list of potential changes for
Python 3000.

Georg
 
S

Steven D'Aprano

Steven said:
Bart Willems wrote:
James Stroud wrote:
... It boils down to the fact that tuples are useless as a result
unless you know you really need them--and you never really NEED them.
Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.

"Impossible" is a strong word, as is "need" (especially when in all caps).

py> import md5
py> class HashedList(list):
... def __hash__(self):
... h = md5.new()
... for item in self:
... h.update(str(hash(item)))
... return int(h.hexdigest(), 16)
...
py> hl = HashedList('bob', 'carol', 'ted')
py> {hl:3}
{['bob', 'carol', 'ted']: 3}

Impossible? I wouldn't even say that this was all that difficult.

Possible, if by possible you mean "broken".

D = {hl: 3}
D {['bob', 'carol', 'ted']: 3}
hl[0] = 'Bob'
D {['Bob', 'carol', 'ted']: 3}
D.keys()[0] is hl True
D[hl]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ['Bob', 'carol', 'ted']

def __setitem__(self, *args):
raise TypeError, '%s doesn't support item assignment.' %
self.__class__.__name__


Problem fixed. Next?

hl.reverse()
hl.sort() # if the list isn't already sorted
del hl[0]
hl.append()
etc.


Yes, you can block those as well... but by the time you've finished making
your HashedList immutable, it is just a slower tuple with a different
name.

In other words... you can avoid using tuples by using a tuple with a
different name. You might as well just do this:

HashedList = tuple
 
C

Carsten Haese

Will tuples also get a sort method? What about append and extend? pop?
__iadd__? __delslice__?

Since tuples are immutable, no.
[...]

If you see tuples as an immutable list, having an index method is quite
useful. If you see them as structs, an index method is useless.

Let's recall what GvR said:

"""
For tuples, I suspect such a function would rarely be used; I think
that is most cases where x.index() would be useful, x is generally a
list, whose contents varies in time, rather than a tuple (which cannot
change easily).
"""

In Guido's opinion, it's not the "structness" of tuples that negates the
need for tuple.index, it's their inability to be mutated easily. So
Guido seems to disagree with your notion that an index method is quite
useful for immutable lists.

I won't presume to speak for Guido, but if I had to connect the dots
between "tuples are immutable" and "tuples will rarely need an index
method", I'd do it like this: Consider an object X and a tuple T. Tuples
have "X in T" tests, so you can check if there exists some N such that
T[N]==X. The lack of the index method means you won't know the value of
N, but what would knowing N give you? You can't modify T, so all you can
do is read T[N], but you already know that that's going to return X, so
you might as well just use X.

Any use case for actually having to know N would have to involve an
operation where you end up explicitly using an index other than N, such
as slicing T from 0 to N-1, or looking at T[2*N] or something like that.
Of course such operations might be useful, but algorithms that need an
operation like that would self-document their design more clearly by
using a list instead of a tuple.

I hope this explains at least to some people how this seemingly
gratuitous inconsistency can actually be viewed as a justified design
decision.

-Carsten
 
O

OKB (not okblacke)

Carsten said:
I won't presume to speak for Guido, but if I had to connect the
dots between "tuples are immutable" and "tuples will rarely need an
index method", I'd do it like this: Consider an object X and a
tuple T. Tuples have "X in T" tests, so you can check if there
exists some N such that T[N]==X. The lack of the index method means
you won't know the value of N, but what would knowing N give you?
You can't modify T, so all you can do is read T[N], but you already
know that that's going to return X, so you might as well just use
X.

Any use case for actually having to know N would have to involve an
operation where you end up explicitly using an index other than N,
such as slicing T from 0 to N-1, or looking at T[2*N] or something
like that. Of course such operations might be useful, but
algorithms that need an operation like that would self-document
their design more clearly by using a list instead of a tuple.

This is a reasonable argument, but all such arguments miss what I
think is an important use case for tuples: you want a list, but you need
to use it as a dictionary key.

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
J

James Stroud

Steven said:
Steven said:
On Mon, 09 Apr 2007 02:26:37 +0000, James Stroud wrote:


Bart Willems wrote:

James Stroud wrote:

... It boils down to the fact that tuples are useless as a result
unless you know you really need them--and you never really NEED them.

Could you clarify that for me? I use tuples *a lot* and I really *NEED*
them - I'm building a lot of multi-tier reports where detail-level data
is pulled out of a dictionary based on a composed key. It is impossible
to build those dictionaries *without* using tuples.

"Impossible" is a strong word, as is "need" (especially when in all caps).

py> import md5
py> class HashedList(list):
... def __hash__(self):
... h = md5.new()
... for item in self:
... h.update(str(hash(item)))
... return int(h.hexdigest(), 16)
...
py> hl = HashedList('bob', 'carol', 'ted')
py> {hl:3}
{['bob', 'carol', 'ted']: 3}

Impossible? I wouldn't even say that this was all that difficult.

Possible, if by possible you mean "broken".



D = {hl: 3}
D

{['bob', 'carol', 'ted']: 3}

hl[0] = 'Bob'
D

{['Bob', 'carol', 'ted']: 3}

D.keys()[0] is hl

True

D[hl]

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ['Bob', 'carol', 'ted']

def __setitem__(self, *args):
raise TypeError, '%s doesn't support item assignment.' %
self.__class__.__name__


Problem fixed. Next?


hl.reverse()
hl.sort() # if the list isn't already sorted
del hl[0]
hl.append()
etc.


Yes, you can block those as well...

To prevent abuse.

but by the time you've finished making
your HashedList immutable, it is just a slower tuple with a different
name.

But has an index() method.
In other words... you can avoid using tuples by using a tuple with a
different name. You might as well just do this:

HashedList = tuple

You can avoid using tuples any number of ways. For example, you can
catenate strings.

You seem to be under the misapprehension that I authored the Subjet
line. Please read the original quote:
> It boils down to the fact that tuples are useless as a result unless
> you know you really need them--and you never really NEED them.

Bear in mind that this was also a response to someone admittedly less
familiar to the language--to encourage him to use lists in favor of
tuples to avoid inconveniences later.

The HashedList is to show that you can always get around the requirement
for a tuple and thus an absolute need for a tuple doesn't exist, as
implied by the quote. I make no assertions as to the HashedLists
efficiency. I use tuples all of the time, but I could just as well
catenate strings etc. They are a language convenience that are
ultimately dispensible.

James
 
A

Antoon Pardon

Except that that wasn't the only justification. GvR also said:

"""
For tuples, I suspect such a function would rarely be used; I think
that is most cases where x.index() would be useful, x is generally a
list, whose contents varies in time, rather than a tuple (which cannot
change easily).
"""

The lack of convincing use cases is still a pertinent reason today. Note
that the original poster on this thread did not present a use case for
tuple.index, they were only asking out of curiosity.

If you have a use case for tuple.index, please show it to me, and I'll
show you what you should be using instead of a tuple.

No wonder no convincing use cases for tuples have shown up. You just
defined use cases of tuples as unconvincing.

My personal opinion is that lack of use cases are used too much as an
excuse. Limiting the development of your language to use cases makes
your language less consistent and so makes your language less easy to
learn.

Of course it also limits the language to what the developers can think off.
I once thought it would be usefull to have something like a slice but
with extended functionality. So I first tried this:

class Islice(slice):
...

and I got:

type 'slice' is not an acceptable base type


then I just tried:

class Islice:
...

But an instance of such a class can't be used as an index, despited the
propoganda that is made for duck typing in this news group.

I guess the developers just couldn't see the use case of this.

But you do have to wonder when the developers started to unify classes
and types, why they just didn't go the whole wayr?. Making all types
subclassable, means you have only one case to code and the user doesn't
has to wonder whether a particular type is subclassable or not. I think
that is a bigger gain, than the potential loss one may experience
because some type that now are subclassable will never actually be
subclassed.
 
A

Antoon Pardon

It remains to be proven that it is an inconsistency, rather than a design
decision.

The two don't contradict. A design decision can introduce an
inconsistency. AFAICS having an index method on tuples seems
rather natural. Looking for the index of a particular item in
your sequence seems just as usefull independant of the nature
of your sequence. So unless there is some rather forcefull
argument it seems inconsistent to have some sequences lacking
this method.
 
A

Antoon Pardon

When a new feature is requested, the burden of proof is on the requester
to show that it has uses.

I don't agree. Good or bad design is not dependant on what is
implemented and what is not.
The use case for not having tuple.index is
that there are no use cases for having it. If that answer sounds absurd,
it is because your question is absurd.

You mean that those who are against tuple.index won't find any use case
convincing enough.
 
D

Duncan Booth

Antoon Pardon said:
I don't agree. Good or bad design is not dependant on what is
implemented and what is not.

There is a cost to every new language feature: it has to be implemented,
documented, maintained, and above all learned by the users. Good design
involves, in part, not adding to these burdens except where there is a
benefit at least equal to the cost.
You mean that those who are against tuple.index won't find any use case
convincing enough.
Why not try them? Pose a few useful cases where the existence of
tuple.index() would actually give a benefit and see what response you get.

You would have to meet a few obvious conditions: the use case would need to
be one where a tuple was preferable to a list (the obvious one being where
you need to hash it), the tuple would have to be sufficiently long or the
calls to 'index' sufficiently frequent to make casting to a list so you can
call 'list(obj).index(...)' unattractive, and you actually need a reason to
be using 'index' rather than just the 'in' operator.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,273
Latest member
DamonShoem

Latest Threads

Top