Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #99091 > unrolled thread

Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?)

Started byLaura Creighton <lac@openend.se>
First post2015-11-19 21:18 +0100
Last post2015-11-25 10:13 +0100
Articles 20 on this page of 86 — 17 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Laura Creighton <lac@openend.se> - 2015-11-19 21:18 +0100
    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-19 22:57 +0200
      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Laura Creighton <lac@openend.se> - 2015-11-19 23:41 +0100
        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-20 14:00 +0000
      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-20 11:33 +1100
        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-25 09:14 +0100
          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-25 21:52 +1100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-25 13:25 +0100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 13:20 +0000
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ned Batchelder <ned@nedbatchelder.com> - 2015-11-25 07:13 -0800
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Laura Creighton <lac@openend.se> - 2015-11-25 16:59 +0100
                  Multiplication [was Re: Late-binding of function defaults] Steven D'Aprano <steve@pearwood.info> - 2015-11-26 05:09 +1100
                    Re: Multiplication [was Re: Late-binding of function defaults] Laura Creighton <lac@openend.se> - 2015-11-25 19:45 +0100
                    Re: Multiplication [was Re: Late-binding of function defaults] Marko Rauhamaa <marko@pacujo.net> - 2015-11-25 23:04 +0200
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Arie van Wingerden <xapwing@gmail.com> - 2015-11-25 17:12 +0100
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 03:29 +1100
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 17:18 +0000
                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ian Kelly <ian.g.kelly@gmail.com> - 2015-11-25 11:03 -0700
                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 18:48 +0000
                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-11-25 20:50 +0000
                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 21:56 +0000
                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 00:16 +0200
                        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 22:41 +0000
                          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-26 11:31 +1100
                            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-26 01:23 +0000
                              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ned Batchelder <ned@nedbatchelder.com> - 2015-11-25 17:52 -0800
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ben Finney <ben+python@benfinney.id.au> - 2015-11-26 16:08 +1100
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-11-26 06:39 +0000
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-26 09:31 +0100
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-26 12:53 +0000
                                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-27 00:15 +1100
                                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-26 14:40 +0000
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) MRAB <python@mrabarnett.plus.com> - 2015-11-26 16:14 +0000
                                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-26 22:27 +0000
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-27 10:07 +1100
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Random832 <random832@fastmail.com> - 2015-11-26 19:15 -0500
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-27 11:48 +1100
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) MRAB <python@mrabarnett.plus.com> - 2015-11-27 01:15 +0000
                                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) MRAB <python@mrabarnett.plus.com> - 2015-11-26 16:16 +0000
                                  Re: Late-binding of function defaults (was Re: What is a function   parameter =[] for?) Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2015-11-27 10:48 +1300
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-27 12:46 +1100
                                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-27 02:01 +0000
                              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 08:41 +0200
                              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-27 12:09 +1100
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-27 10:31 +0000
                                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-27 13:30 +0200
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ben Finney <ben+python@benfinney.id.au> - 2015-11-26 06:57 +1100
                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-25 23:00 +0200
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Emile van Sebille <emile@fenx.com> - 2015-11-25 10:56 -0800
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-26 13:01 +1100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 00:24 +1100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-25 15:17 +0100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Emile van Sebille <emile@fenx.com> - 2015-11-25 10:51 -0800
        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-25 19:32 +1100
          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-25 10:43 +0200
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-25 21:58 +1100
          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 12:35 +0000
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-25 15:06 +0200
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 13:37 +0000
                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-25 15:53 +0200
                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) BartC <bc@freeuk.com> - 2015-11-25 14:34 +0000
                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2015-11-25 13:32 -0500
                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-26 11:53 +1100
                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 08:52 +0200
                        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 18:14 +1100
                          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 10:27 +0200
                            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 19:34 +1100
                              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 12:54 +0200
                                Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 22:04 +1100
                                  Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 13:23 +0200
                                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 22:35 +1100
                                      Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 14:03 +0200
                                    Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-27 12:43 +1100
                            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-26 09:45 +0100
                            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2015-11-27 10:20 +1300
                              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Marko Rauhamaa <marko@pacujo.net> - 2015-11-26 23:36 +0200
                            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Steven D'Aprano <steve@pearwood.info> - 2015-11-27 12:23 +1100
                        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-11-26 11:17 +0000
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 00:44 +1100
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ben Finney <ben+python@benfinney.id.au> - 2015-11-26 06:55 +1100
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Random832 <random832@fastmail.com> - 2015-11-26 00:52 +0000
              Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Ian Kelly <ian.g.kelly@gmail.com> - 2015-11-25 20:01 -0700
              Semantics of collection types (was: Late-binding of function defaults (was Re: What is a function parameter =[] for?)) Ben Finney <ben+python@benfinney.id.au> - 2015-11-26 16:04 +1100
            Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Chris Angelico <rosuav@gmail.com> - 2015-11-26 00:35 +1100
          Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Larry Hudson <orgnut@yahoo.com> - 2015-11-25 22:44 -0800
        Re: Late-binding of function defaults (was Re: What is a function parameter =[] for?) Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2015-11-25 10:13 +0100

Page 4 of 5 — ← Prev page 1 2 3 [4] 5  Next page →


#99457

FromBartC <bc@freeuk.com>
Date2015-11-25 14:34 +0000
Message-ID<n34gor$kq8$1@dont-email.me>
In reply to#99453
On 25/11/2015 13:53, Marko Rauhamaa wrote:
> BartC <bc@freeuk.com>:
>
>> Using tuples in the same way that other languages implement records is
>> going to be difficult if you can't change the values of the fields!
>
> Guido could decide tomorrow that tuples are mutable.

(Could that be done without breaking existing code? And what then would 
be the difference between them and lists?)

> Anyway, Python has two ways to represent records: classes and tuples.
> Tuples are nice because they are concise and ad hoc. Often you start
> with a scalar value, then turn it into a tuple. After a while your handy
> tuple turns out a bit cumbersome to use so you convert it into an actual
> class.

This is how records are handled in another language which I believe is 
simpler than Python: http://pastebin.com/vhsJML8U

This also implements my example from earlier in the thread. Now compare 
with Python's approach.

OK, that also needs two concepts, a list, and a record. But the 
distinction is now completely obvious. Records are also mutable. It 
would also be clear why you can't append to a record.

Now try explaining again to me how you would use tuples for the same 
thing...

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#99475

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2015-11-25 13:32 -0500
Message-ID<mailman.86.1448476375.20593.python-list@python.org>
In reply to#99457
On Wed, 25 Nov 2015 14:34:12 +0000, BartC <bc@freeuk.com> declaimed the
following:

>On 25/11/2015 13:53, Marko Rauhamaa wrote:
>Now try explaining again to me how you would use tuples for the same 
>thing...

	You wouldn't -- you would decompose the tuple and create a new one from
the parts, with changes as needed.

	And as hinted, tuples were immutable in Python so they could be used as
keys in dictionaries.  The associated concept then also makes sense --
lists commonly holding multiple independent entities of the same type vs an
ordered collection of dependent entities of different types.

	And tuple, as used by Python, is a close match to tuple as used by
relational theory -- everything in the tuple is related in some way. If one
is to make a change to a component of a relational tuple, it is no longer
the same tuple.
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#99515

FromSteven D'Aprano <steve@pearwood.info>
Date2015-11-26 11:53 +1100
Message-ID<56565822$0$1617$c3e8da3$5496439d@news.astraweb.com>
In reply to#99457
On Thu, 26 Nov 2015 01:34 am, BartC wrote:

> On 25/11/2015 13:53, Marko Rauhamaa wrote:
>> BartC <bc@freeuk.com>:
>>
>>> Using tuples in the same way that other languages implement records is
>>> going to be difficult if you can't change the values of the fields!
>>
>> Guido could decide tomorrow that tuples are mutable.
> 
> (Could that be done without breaking existing code? And what then would
> be the difference between them and lists?)


No it could not, and no Guido could not decide to make them mutable. 

Well, strictly speaking he could make that decision, but the other core
developers would not go along with such a stupid backwards-incompatible
change. I don't know what would happen if Guido did make that decision -- I
suppose it would provoke some sort of constitutional crisis (figuratively
speaking), like what would happen if the Queen of the UK refused to sign
into law legislation after being lawfully asked to do so by the Prime
Minister. (The Queen has the power to reject any legislation put to her by
the Prime Minister, so long as she does not actually make use of that
power.)

Guido, as BDFL, has every right to make tuples mutable, or remove numbers
from the language, so long as he does not actually do so.

Making tuples mutable would break their use as dictionary keys, which is a
*critical* use.

https://docs.python.org/2/faq/design.html#why-must-dictionary-keys-be-immutable



>> Anyway, Python has two ways to represent records: classes and tuples.
>> Tuples are nice because they are concise and ad hoc. Often you start
>> with a scalar value, then turn it into a tuple. After a while your handy
>> tuple turns out a bit cumbersome to use so you convert it into an actual
>> class.
> 
> This is how records are handled in another language which I believe is
> simpler than Python: http://pastebin.com/vhsJML8U
> 
> This also implements my example from earlier in the thread. Now compare
> with Python's approach.
> 
> OK, that also needs two concepts, a list, and a record. But the
> distinction is now completely obvious. Records are also mutable. It
> would also be clear why you can't append to a record.
> 
> Now try explaining again to me how you would use tuples for the same
> thing...

In Pascal, strings are mutable. (Well, technically, standard Pascal doesn't
define a string data type, but most implementations do.) So you typically
have some function like:

insert(thestring, substring, pos)

which modifies thestring in place. In Python, strings are immutable, so the
equivalent of insert() would be a function that returns a new string:

thestring = insert(thestring, substring, pos)

It's not exactly an earth-shattering difference.

The implementation is simple that it is almost pointless to put it in a
function:

def insert(s, substring, pos):
    return s[:pos] + substring + s[pos:]


Tuples-as-records are no different. Instead of modifying the existing
record, you create a new one. If that's inconvenient, then use a class,
which will be mutable by default.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#99532

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 08:52 +0200
Message-ID<87oaeh2qy0.fsf@elektro.pacujo.net>
In reply to#99515
Steven D'Aprano <steve@pearwood.info>:

> Making tuples mutable would break their use as dictionary keys, which is a
> *critical* use.

No, it wouldn't. Any object that provides __hash__() and __eq__() can be
used as a key.

Nothing prevents using mutable objects as keys in Python.

    Egon Spengler: There's something very important I forgot to tell you.
    Peter Venkman: What?
    Spengler: Don't use mutable keys.
    Venkman: Why?
    Spengler: It would be bad.
    Venkman: I'm fuzzy on the whole good/bad thing. What do you mean,
       "bad"?
    Spengler: Try to imagine all life as you know it stopping
        instantaneously and every molecule in your body exploding at the
        speed of light.
    Ray Stantz: Total protonic reversal!
    Venkman: Right. That's bad. Okay. All right. Important safety tip.
        Thanks, Egon.


Marko

[toc] | [prev] | [next] | [standalone]


#99536

FromChris Angelico <rosuav@gmail.com>
Date2015-11-26 18:14 +1100
Message-ID<mailman.117.1448525450.20593.python-list@python.org>
In reply to#99532
On Thu, Nov 26, 2015 at 5:52 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Steven D'Aprano <steve@pearwood.info>:
>
>> Making tuples mutable would break their use as dictionary keys, which is a
>> *critical* use.
>
> No, it wouldn't. Any object that provides __hash__() and __eq__() can be
> used as a key.
>
> Nothing prevents using mutable objects as keys in Python.
>
>

Sure, you _can_. But if the key's hash changes between dict insertion
and retrieval, all manner of invariants will break, and likewise if
two equal objects have different hashes. From which you can deduce
logically that any object used as a key must remain (not) equal to
everything that it was (not) equal to from that time until it is
looked up... which basically means its value mustn't change. It must
be immutable.

ChrisA

[toc] | [prev] | [next] | [standalone]


#99538

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 10:27 +0200
Message-ID<87a8q1f9ni.fsf@elektro.pacujo.net>
In reply to#99536
Chris Angelico <rosuav@gmail.com>:

> On Thu, Nov 26, 2015 at 5:52 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>> Nothing prevents using mutable objects as keys in Python.
>
> Sure, you _can_. But if the key's hash changes between dict insertion
> and retrieval, all manner of invariants will break, and likewise if
> two equal objects have different hashes. From which you can deduce
> logically that any object used as a key must remain (not) equal to
> everything that it was (not) equal to from that time until it is
> looked up... which basically means its value mustn't change. It must
> be immutable.

What I'm saying is that Python does not prevent mutable keys but tries
to do that with lists and tuples.

I think Python should stop trying.

I have wanted to use lists as keys, and there should be no reason to
allow mutable tuples. It should be enough to say that the behavior of a
dictionary is undefined if a key should mutate on the fly.


Marko

[toc] | [prev] | [next] | [standalone]


#99541

FromChris Angelico <rosuav@gmail.com>
Date2015-11-26 19:34 +1100
Message-ID<mailman.120.1448526890.20593.python-list@python.org>
In reply to#99538
On Thu, Nov 26, 2015 at 7:27 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Chris Angelico <rosuav@gmail.com>:
>
>> On Thu, Nov 26, 2015 at 5:52 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>> Nothing prevents using mutable objects as keys in Python.
>>
>> Sure, you _can_. But if the key's hash changes between dict insertion
>> and retrieval, all manner of invariants will break, and likewise if
>> two equal objects have different hashes. From which you can deduce
>> logically that any object used as a key must remain (not) equal to
>> everything that it was (not) equal to from that time until it is
>> looked up... which basically means its value mustn't change. It must
>> be immutable.
>
> What I'm saying is that Python does not prevent mutable keys but tries
> to do that with lists and tuples.
>
> I think Python should stop trying.
>
> I have wanted to use lists as keys, and there should be no reason to
> allow mutable tuples. It should be enough to say that the behavior of a
> dictionary is undefined if a key should mutate on the fly.

Python defines dict-key-validity as being synonymous with hashability.
It's up to the class author to make sure the object's hash is useful.

Behaviour being undefined works just fine [1] in C. It's not so
popular in Python. I don't think we want to have myriad new and
experienced programmers trying to figure out why square brackets in
dict keys are usually fine but occasionally not.

ChrisA

[1] For some definition of "fine", anyway.

[toc] | [prev] | [next] | [standalone]


#99550

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 12:54 +0200
Message-ID<87610pf2uq.fsf@elektro.pacujo.net>
In reply to#99541
Chris Angelico <rosuav@gmail.com>:

> On Thu, Nov 26, 2015 at 7:27 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>> I have wanted to use lists as keys, and there should be no reason to
>> allow mutable tuples. It should be enough to say that the behavior of
>> a dictionary is undefined if a key should mutate on the fly.
>
> Python defines dict-key-validity as being synonymous with hashability.
> It's up to the class author to make sure the object's hash is useful.

   >>> hash([])
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: unhashable type: 'list'

Annoying.

> Behaviour being undefined works just fine [1] in C. It's not so
> popular in Python. I don't think we want to have myriad new and
> experienced programmers trying to figure out why square brackets in
> dict keys are usually fine but occasionally not.

But there's no way to enforce that with any of the myriad new classes.

   Ye blind guides, which strain at a gnat, and swallow a camel.

But I say unto you, Swallow the gnat as well.


Marko

[toc] | [prev] | [next] | [standalone]


#99552

FromChris Angelico <rosuav@gmail.com>
Date2015-11-26 22:04 +1100
Message-ID<mailman.127.1448535849.20593.python-list@python.org>
In reply to#99550
On Thu, Nov 26, 2015 at 9:54 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Chris Angelico <rosuav@gmail.com>:
>
>> On Thu, Nov 26, 2015 at 7:27 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>> I have wanted to use lists as keys, and there should be no reason to
>>> allow mutable tuples. It should be enough to say that the behavior of
>>> a dictionary is undefined if a key should mutate on the fly.
>>
>> Python defines dict-key-validity as being synonymous with hashability.
>> It's up to the class author to make sure the object's hash is useful.
>
>    >>> hash([])
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in <module>
>    TypeError: unhashable type: 'list'
>
> Annoying.

Yes, it's really annoying that you get an immediate exception instead
of unpredictably getting bizarre failures that depend on the exact
bucket sizes and dict size and so on. It's such a pain to get told
exactly where the problem is.

>> Behaviour being undefined works just fine [1] in C. It's not so
>> popular in Python. I don't think we want to have myriad new and
>> experienced programmers trying to figure out why square brackets in
>> dict keys are usually fine but occasionally not.
>
> But there's no way to enforce that with any of the myriad new classes.

Python tends to assume that programmers are intelligent people who are
prepared to fix their mistakes. As a general rule, if you define
__eq__, you should probably define __hash__ as well, and then you need
to know what you're doing; specifically, the invariant that if a==b,
hash(a)==hash(b). Python doesn't enforce that because it's impossible
to enforce.

ChrisA

[toc] | [prev] | [next] | [standalone]


#99557

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 13:23 +0200
Message-ID<87wpt5dmxg.fsf@elektro.pacujo.net>
In reply to#99552
Chris Angelico <rosuav@gmail.com>:

> On Thu, Nov 26, 2015 at 9:54 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>
>>    >>> hash([])
>>    Traceback (most recent call last):
>>      File "<stdin>", line 1, in <module>
>>    TypeError: unhashable type: 'list'
>>
>> Annoying.
>
> Yes, it's really annoying that you get an immediate exception instead
> of unpredictably getting bizarre failures that depend on the exact
> bucket sizes and dict size and so on. It's such a pain to get told
> exactly where the problem is.

The problem is that lists don't have __hash__ and __eq__ defined.

> Python tends to assume that programmers are intelligent people who are
> prepared to fix their mistakes.

It's not letting me in the case of list.


Marko

[toc] | [prev] | [next] | [standalone]


#99561

FromChris Angelico <rosuav@gmail.com>
Date2015-11-26 22:35 +1100
Message-ID<mailman.131.1448537758.20593.python-list@python.org>
In reply to#99557
On Thu, Nov 26, 2015 at 10:23 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
> Chris Angelico <rosuav@gmail.com>:
>
>> On Thu, Nov 26, 2015 at 9:54 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>>
>>>    >>> hash([])
>>>    Traceback (most recent call last):
>>>      File "<stdin>", line 1, in <module>
>>>    TypeError: unhashable type: 'list'
>>>
>>> Annoying.
>>
>> Yes, it's really annoying that you get an immediate exception instead
>> of unpredictably getting bizarre failures that depend on the exact
>> bucket sizes and dict size and so on. It's such a pain to get told
>> exactly where the problem is.
>
> The problem is that lists don't have __hash__ and __eq__ defined.

They do define equality. And it depends on their contents, ergo there
cannot be a stable hash. This is NOT a problem. This is the concept of
unhashability behaving EXACTLY CORRECTLY. Sorry to shout, but this is
another case of refusing to accept what has been explained as having
good reason, and I'm getting a little tired of it.

>> Python tends to assume that programmers are intelligent people who are
>> prepared to fix their mistakes.
>
> It's not letting me in the case of list.

Actually it is. Your mistake is trying to use a list as a dict key.
You have a solution available: use a tuple.

ChrisA

[toc] | [prev] | [next] | [standalone]


#99565

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 14:03 +0200
Message-ID<87oaehdl24.fsf@elektro.pacujo.net>
In reply to#99561
Chris Angelico <rosuav@gmail.com>:

> On Thu, Nov 26, 2015 at 10:23 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>> It's not letting me in the case of list.
>
> Actually it is. Your mistake is trying to use a list as a dict key.
> You have a solution available: use a tuple.

Yes, or wrap the list in a class.


Marko

[toc] | [prev] | [next] | [standalone]


#99616

FromSteven D'Aprano <steve@pearwood.info>
Date2015-11-27 12:43 +1100
Message-ID<5657b52c$0$1617$c3e8da3$5496439d@news.astraweb.com>
In reply to#99557
On Thu, 26 Nov 2015 10:23 pm, Marko Rauhamaa wrote:

> Chris Angelico <rosuav@gmail.com>:
> 
>> On Thu, Nov 26, 2015 at 9:54 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>>
>>>    >>> hash([])
>>>    Traceback (most recent call last):
>>>      File "<stdin>", line 1, in <module>
>>>    TypeError: unhashable type: 'list'
>>>
>>> Annoying.
>>
>> Yes, it's really annoying that you get an immediate exception instead
>> of unpredictably getting bizarre failures that depend on the exact
>> bucket sizes and dict size and so on. It's such a pain to get told
>> exactly where the problem is.
> 
> The problem is that lists don't have __hash__ and __eq__ defined.


I'm pretty sure that lists have __eq__ defined :-P



>> Python tends to assume that programmers are intelligent people who are
>> prepared to fix their mistakes.
> 
> It's not letting me in the case of list.


Less whining, more programming:

class MyList(list):
    def __hash__(self):
        return 1


There you go, problem solved. New problems are your responsibility:


py> a = MyList([1, 2])
py> d = {a: "spam"}
py> d[MyList([1, 2])]  # Looks good so far.
'spam'
py> a.append(3)
py> d[MyList([1, 2])]  # Where did my key go?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: [1, 2]


py> b = MyList([1, 3])
py> d[b] = "eggs"
py> d[MyList([1, 3])]  # So far so good.
'eggs'
py> b[1] -= 1
py> b.append(3)
py> d[b]  # What?
'spam'


All I can say is, this would be an absolutely awesome feature for Python to
have, if you were being paid by the hour for debugging.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#99545

FromAntoon Pardon <antoon.pardon@rece.vub.ac.be>
Date2015-11-26 09:45 +0100
Message-ID<mailman.124.1448527548.20593.python-list@python.org>
In reply to#99538
Op 26-11-15 om 09:27 schreef Marko Rauhamaa:
> Chris Angelico <rosuav@gmail.com>:
>
>> On Thu, Nov 26, 2015 at 5:52 PM, Marko Rauhamaa <marko@pacujo.net> wrote:
>>> Nothing prevents using mutable objects as keys in Python.
>> Sure, you _can_. But if the key's hash changes between dict insertion
>> and retrieval, all manner of invariants will break, and likewise if
>> two equal objects have different hashes. From which you can deduce
>> logically that any object used as a key must remain (not) equal to
>> everything that it was (not) equal to from that time until it is
>> looked up... which basically means its value mustn't change. It must
>> be immutable.
> What I'm saying is that Python does not prevent mutable keys but tries
> to do that with lists and tuples.
>
> I think Python should stop trying.
>
> I have wanted to use lists as keys, and there should be no reason to
> allow mutable tuples. It should be enough to say that the behavior of a
> dictionary is undefined if a key should mutate on the fly.

Maybe python could introduce a dictionary that copies the keys in and
out the dictionary. In that case keys can be mutable without that being
a problem for the dictionary, because the dictionary works with it's own
copy of the key that it doesn't mutate.

-- 
Antoon.

[toc] | [prev] | [next] | [standalone]


#99599

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2015-11-27 10:20 +1300
Message-ID<dbpbdrFce6nU1@mid.individual.net>
In reply to#99538
Marko Rauhamaa wrote:
> What I'm saying is that Python does not prevent mutable keys but tries
> to do that with lists and tuples.
> 
> I think Python should stop trying.

Do you volunteer to answer all the posts from beginners
complaining that "the dict type is broken" because they
used a list as a key and then mutated it?

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#99600

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-11-26 23:36 +0200
Message-ID<87egfc30ky.fsf@elektro.pacujo.net>
In reply to#99599
Gregory Ewing <greg.ewing@canterbury.ac.nz>:

> Marko Rauhamaa wrote:
>> What I'm saying is that Python does not prevent mutable keys but
>> tries to do that with lists and tuples.
>>
>> I think Python should stop trying.
>
> Do you volunteer to answer all the posts from beginners complaining
> that "the dict type is broken" because they used a list as a key and
> then mutated it?

What happened to consenting adults?

Even Java (of all languages) allows lists to be keys and simply notes:

   Note: great care must be exercised if mutable objects are used as map
   keys.

   <URL: http://docs.oracle.com/javase/7/docs/api/java/util/Map.html>


Marko

[toc] | [prev] | [next] | [standalone]


#99611

FromSteven D'Aprano <steve@pearwood.info>
Date2015-11-27 12:23 +1100
Message-ID<5657b081$0$1586$c3e8da3$5496439d@news.astraweb.com>
In reply to#99538
On Thu, 26 Nov 2015 07:27 pm, Marko Rauhamaa wrote:

> What I'm saying is that Python does not prevent mutable keys but tries
> to do that with lists and tuples.
> 
> I think Python should stop trying.
> 
> I have wanted to use lists as keys, and there should be no reason to
> allow mutable tuples. It should be enough to say that the behavior of a
> dictionary is undefined if a key should mutate on the fly.

Well, when you design your own language, you can make all the bad design
decisions you like :-)

Seriously, if you think *this* thread about mutable function defaults has
been long, can you imagine the bug reports and arguments if this was
possible in Python?


L = [1, 2]
d = {L: "found it"}

# much later, after L has been modified...

d[ [1, 2] ]
=> raises KeyError



But even worse:


a = [1, 2]
b = [1, 3]
d = {a: "spam", b: "ham"}
a[1] += 1

What will d[ [1, 3] ] return?


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#99556

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-11-26 11:17 +0000
Message-ID<mailman.128.1448536715.20593.python-list@python.org>
In reply to#99532
On 26/11/2015 06:52, Marko Rauhamaa wrote:
> Steven D'Aprano <steve@pearwood.info>:
>
>> Making tuples mutable would break their use as dictionary keys, which is a
>> *critical* use.
>
> No, it wouldn't. Any object that provides __hash__() and __eq__() can be
> used as a key.
>

Almost, see https://wiki.python.org/moin/DictionaryKeys.  Under the 
title "Types Usable as Dictionary Keys" it states "The discussion above 
should explain why Python requires that:

To be used as a dictionary key, an object must support the hash function 
(e.g. through __hash__), equality comparison (e.g. through __eq__ or 
__cmp__), and must satisfy the correctness condition above."

The correctness condition is:-

"For such a lookup algorithm to work correctly, the hash functions 
provided must guarantee that if two keys produce different hash values 
then the two key objects are not equivalent, that is,

for all i1, i2, if hash(i1) != hash(i2), then i1 != i2"

Aren't search engines just wonderful :)

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#99450

FromChris Angelico <rosuav@gmail.com>
Date2015-11-26 00:44 +1100
Message-ID<mailman.71.1448459080.20593.python-list@python.org>
In reply to#99445
On Thu, Nov 26, 2015 at 12:06 AM, Marko Rauhamaa <marko@pacujo.net> wrote:
> However, tuples are a way to represent records, groupings of related
> values, where the semantics of each value is determined by its position
> in the tuple. The members in a tuple are typically of different data
> types.
>
> Lists are collections of values. Typically, each member of list is of
> the same type.

This is a distinction I generally make. Putting it another way: a list
has the same meaning regardless of how many items are on it (for
instance, a shopping list is still a shopping list whether it has five
or fifty items on it), where a tuple is a package where each element
has a specific meaning (such as Cartesian coordinates; the difference
between the position (2,3) and the position (2,3,4) is not just that
there's "more position" in the second one - it's a drastically
different beast, living in three dimensions instead of two).

Nothing in the language enforces this, but the mutability of lists
does tend to align well with things that can grow and shrink, and the
immutability of tuples makes them more like strings or complex numbers
(in fact, a complex number is basically a tuple of two floats).

ChrisA

[toc] | [prev] | [next] | [standalone]


#99480

FromBen Finney <ben+python@benfinney.id.au>
Date2015-11-26 06:55 +1100
Message-ID<mailman.90.1448481340.20593.python-list@python.org>
In reply to#99445
Chris Angelico <rosuav@gmail.com> writes:

> This is a distinction I generally make. Putting it another way: a list
> has the same meaning regardless of how many items are on it (for
> instance, a shopping list is still a shopping list whether it has five
> or fifty items on it), where a tuple is a package where each element
> has a specific meaning […]

Yes. The disctinction is even clearer, I find, by saying that the
*meaning of the position* in the sequence is significant for a tuple,
not significant for a list.

That is, the ‘2’ in ‘cartesian_point = (2, 3)’ means something different
than in ‘cartesian_point = (3, 2)’.

Whereas the ‘2’ in ‘test_scores = [2, 3]’ means exactly the same as in
‘test_scores = [3, 2]’.

If each position in the sequence gives the value there a different
menaning, use a tuple; if not, use a list.

> Nothing in the language enforces this, but the mutability of lists
> does tend to align well with things that can grow and shrink, and the
> immutability of tuples makes them more like strings or complex numbers
> (in fact, a complex number is basically a tuple of two floats).

Not only the growing and shrinking, but the re-ordering of items in a
list should not change the meaning of its items.

If you can ‘sort’ the sequence and the items still mean exactly what
they did before, then a tuple is the wrong type to use, semantically.

-- 
 \       “Crime is contagious… if the government becomes a lawbreaker, |
  `\          it breeds contempt for the law.” —Justice Louis Brandeis |
_o__)                                                                  |
Ben Finney

[toc] | [prev] | [next] | [standalone]


Page 4 of 5 — ← Prev page 1 2 3 [4] 5  Next page →

Back to top | Article view | comp.lang.python


csiph-web