Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #48742 > unrolled thread
| Started by | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| First post | 2013-06-19 12:17 -0700 |
| Last post | 2013-06-20 01:17 +0000 |
| Articles | 20 on this page of 86 — 21 participants |
Back to article view | Back to comp.lang.python
Default Value Ahmed Abdulshafy <abdulshafy@gmail.com> - 2013-06-19 12:17 -0700
Re: Default Value Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-06-19 22:35 +0300
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-19 12:38 -0700
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-20 05:57 -0700
Re: Default Value Roy Smith <roy@panix.com> - 2013-06-20 09:19 -0400
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-20 06:31 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 00:17 +0000
Re: Default Value Roy Smith <roy@panix.com> - 2013-06-20 20:25 -0400
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-20 07:49 -0700
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-21 01:38 +1000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-20 11:05 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 00:57 +0000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-20 20:16 -0700
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-21 17:10 +1000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 07:32 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 16:22 +0000
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 15:57 +0000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 10:01 -0700
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-21 18:47 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 11:26 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 18:37 +0000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 12:18 -0700
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 12:35 -0700
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-22 05:07 +1000
Re: Default Value Neil Cerutti <neilc@norwich.edu> - 2013-06-21 19:20 +0000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 13:27 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-22 01:31 +0000
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-22 11:40 +1000
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 18:42 -0700
Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-22 03:04 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 19:32 -0700
Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-22 20:36 +0100
Re: Default Value Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-06-22 18:51 -0400
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-21 19:43 -0700
Re: Default Value Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-06-22 09:26 +0100
Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-21 20:25 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 13:44 -0700
Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-21 23:49 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 16:51 -0700
Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-22 02:54 +0100
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-22 01:15 +0000
Re: Default Value Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-21 19:27 -0600
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-21 19:32 -0700
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 19:55 -0700
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-21 23:23 -0700
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-22 08:07 -0700
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-22 08:31 -0700
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-22 09:11 -0700
Re: Default Value Grant Edwards <invalid@invalid.invalid> - 2013-06-24 14:22 +0000
Re: [SPAM] Re: Default Value MRAB <python@mrabarnett.plus.com> - 2013-06-24 16:22 +0100
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-22 11:41 +1000
Re: Default Value Michael Torrie <torriem@gmail.com> - 2013-06-21 20:46 -0600
Re: Default Value Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2013-06-22 16:40 +0200
Re: Default Value Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-06-22 12:49 -0400
Re: Default Value Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-22 12:57 -0600
Re: Default Value Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-06-22 18:48 -0400
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-22 00:40 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 18:15 -0700
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-22 11:37 +1000
Re: Default Value Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-21 19:42 -0600
Re: Default Value Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-21 19:38 -0600
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 19:40 -0700
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-22 03:01 +0100
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-22 12:18 +1000
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-22 03:25 +0100
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-22 18:19 +0100
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-22 11:49 -0700
Re: Default Value Rotwang <sg552@hotmail.co.uk> - 2013-06-23 01:49 +0100
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-20 10:12 -0700
Re: Default Value Chris Angelico <rosuav@gmail.com> - 2013-06-21 03:19 +1000
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-20 10:30 -0700
Re: Default Value Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-20 11:57 -0600
Re: Default Value rusi <rustompmody@gmail.com> - 2013-06-20 11:15 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 01:08 +0000
Re: Default Value Tim Chase <python.list@tim.thechases.com> - 2013-06-20 20:26 -0500
Re: Default Value Roy Smith <roy@panix.com> - 2013-06-20 21:40 -0400
Re: Default Value Tim Chase <python.list@tim.thechases.com> - 2013-06-20 21:02 -0500
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-20 11:07 -0700
Re: Default Value alex23 <wuwei23@gmail.com> - 2013-06-21 10:55 +1000
Re: Default Value 88888 Dihedral <dihedral88888@gmail.com> - 2013-06-20 19:18 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 02:26 +0000
Re: Default Value "Lefavor, Matthew (GSFC-582.0)[MICROTEL LLC]" <matthew.lefavor@nasa.gov> - 2013-06-20 17:28 -0500
Re: Default Value Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-21 08:17 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-21 01:28 +0000
Re: Default Value Gary Herron <gherron@digipen.edu> - 2013-06-19 12:57 -0700
Re: Default Value Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-06-20 01:17 +0000
Page 1 of 5 [1] 2 3 4 5 Next page →
| From | Ahmed Abdulshafy <abdulshafy@gmail.com> |
|---|---|
| Date | 2013-06-19 12:17 -0700 |
| Subject | Default Value |
| Message-ID | <7e6361d5-6619-4aaa-adda-8b5f01bde57f@googlegroups.com> |
I'm reading the Python.org tutorial right now, and I found this part rather strange and incomprehensible to me>
Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
This will print
[1]
[1, 2]
[1, 2, 3]
How the list is retained between successive calls? And why?
[toc] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2013-06-19 22:35 +0300 |
| Message-ID | <qotvc59evw5.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #48742 |
Ahmed Abdulshafy <abdulshafy@gmail.com> writes: > I'm reading the Python.org tutorial right now, and I found this part > rather strange and incomprehensible to me > > Important warning: The default value is evaluated only once. This > makes a difference when the default is a mutable object such as a > list, dictionary, or instances of most classes > > def f(a, L=[]): > L.append(a) > return L > > print(f(1)) > print(f(2)) > print(f(3)) > > This will print > [1] > [1, 2] > [1, 2, 3] > > How the list is retained between successive calls? And why? Functions are objects with their own attributes. The default values are computed and stored when the def statement is executed. dir(f) will show the attributes of f. Their names start and end with a double underscore, __. This indicates that they are not usually used explicitly. Still, f.__defaults__ seems to be where the default value is kept between (and during) calls.
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-19 12:38 -0700 |
| Message-ID | <b3d90d37-896c-4c80-8f94-9e046453927c@googlegroups.com> |
| In reply to | #48742 |
On Wednesday, June 19, 2013 2:17:35 PM UTC-5, Ahmed Abdulshafy wrote: > I'm reading the Python.org tutorial right now, and I found > this part rather strange and incomprehensible to me> > > Important warning: The default value is evaluated only > once. This makes a difference when the default is a > mutable object such as a list, dictionary, or instances of > most classes > > def f(a, L=[]): > L.append(a) > return L > > print(f(1)) > print(f(2)) > print(f(3)) > > This will print > > [1] > [1, 2] > [1, 2, 3] > > How the list is retained between successive calls? And > why? By the evil hands of an illogical consistency. Have you ever heard the old adage: "The road to hell is paved in good intentions"? Well, apparently the original designers of the language called in sick the day that class was taught. It's unfortunate because the same functionality that this "intention" claims to solve can be reproduced easily, and in a less astonishing manner, by the programmer himself. http://en.wikipedia.org/wiki/Principle_of_least_astonishment
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-06-20 05:57 -0700 |
| Message-ID | <447dd1c6-1bb2-4276-a109-78d7a067b442@d8g2000pbe.googlegroups.com> |
| In reply to | #48745 |
On Jun 20, 12:38 am, Rick Johnson <rantingrickjohn...@gmail.com> wrote: > On Wednesday, June 19, 2013 2:17:35 PM UTC-5, Ahmed Abdulshafy wrote: > > I'm reading the Python.org tutorial right now, and I found > > this part rather strange and incomprehensible to me> > > > Important warning: The default value is evaluated only > > once. This makes a difference when the default is a > > mutable object such as a list, dictionary, or instances of > > most classes > > > def f(a, L=[]): > > L.append(a) > > return L > > > print(f(1)) > > print(f(2)) > > print(f(3)) > > > This will print > > > [1] > > [1, 2] > > [1, 2, 3] > > > How the list is retained between successive calls? And > > why? > > By the evil hands of an illogical consistency. > > Have you ever heard the old adage: "The road to hell is > paved in good intentions"? Well, apparently the original > designers of the language called in sick the day that class > was taught. It's unfortunate because the same functionality > that this "intention" claims to solve can be reproduced > easily, and in a less astonishing manner, by the programmer > himself. > > http://en.wikipedia.org/wiki/Principle_of_least_astonishment Every language has gotchas. This is one of python's. If you are a beginning python programmer, really the best answer is: Just dont do it! Dont do what? Dont use mutable arguments as function defaults. And when you feel that you need to, use Steven's trick: use a immutable indicator 'None' for the mutable []. Once you cross the noob stage you can check that its a standard gotcha: Just run a search for 'python gotcha default []' Its even been discussed repeatedly on the python-ideas list Heres a correction suggestion: http://mail.python.org/pipermail/python-ideas/2007-January/000073.html Here's Terry Reedy's nicely explaining the 'why-of-the-how' : http://mail.python.org/pipermail/python-ideas/2009-May/004680.html FWIW here is a conceptual/philosophical explanation of your confusion: There are 2 fundamental ways for approaching the programming task -- functional and imperative. In FP, the primary requirement is that the behavior of a function should be entirely determinable by its arguments. In Imp. P, computation proceeds by changing state. Now from the time of Backus turing award http://amturing.acm.org/award_winners/backus_0703524.cfm it is known that the two philosophies are mutually incompatible. Now python is in a rather unique position in this respect: it supports many of the features of modern FPLs and one can almost do functional programming in it. In a few cases the imperative/Object-based internals leak out, this is one of those cases. That such leakage will occasionally happen see: http://www.joelonsoftware.com/articles/LeakyAbstractions.html And you've had a little excess of the FP koolaid read : http://blog.languager.org/2012/08/functional-programming-philosophical.html
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-20 09:19 -0400 |
| Message-ID | <roy-5EEFF8.09194820062013@news.panix.com> |
| In reply to | #48786 |
In article <447dd1c6-1bb2-4276-a109-78d7a067b442@d8g2000pbe.googlegroups.com>, rusi <rustompmody@gmail.com> wrote: > > > def f(a, L=[]): > > > L.append(a) > > > return L > Every language has gotchas. This is one of python's. One of our pre-interview screening questions for Python programmers at Songza is about this. I haven't been keeping careful statistics, but I'd guess only about 50% of the candidates get this right.
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-06-20 06:31 -0700 |
| Message-ID | <011effa3-7afa-4744-a5fe-07d10b1fc059@v5g2000pbv.googlegroups.com> |
| In reply to | #48787 |
On Jun 20, 6:19 pm, Roy Smith <r...@panix.com> wrote: > In article > <447dd1c6-1bb2-4276-a109-78d7a067b...@d8g2000pbe.googlegroups.com>, > > rusi <rustompm...@gmail.com> wrote: > > > > def f(a, L=[]): > > > > L.append(a) > > > > return L > > Every language has gotchas. This is one of python's. > > One of our pre-interview screening questions for Python programmers at > Songza is about this. I haven't been keeping careful statistics, but > I'd guess only about 50% of the candidates get this right. See http://www.cs.utexas.edu/~EWD/transcriptions/EWD04xx/EWD480.html (search forward to 'disastrous blending' ) No I am not saying that such knowledge is not required in the 'real world' However I do feel that just as a view of literature that does not go beyond gothic horror is a poor view; and just because for languages like C (even more C++) expertise more or less equivales gothicness, for a cleaner world like python we should distinguish the seedy areas we know about but avoid and the clean areas we live in. Clearly flagging gotchas as such helps in that direction. In short (and to the OP): If you did NOT find this confusing, it would be cause for more concern :-)
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-06-21 00:17 +0000 |
| Message-ID | <51c39b88$0$29999$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #48787 |
On Thu, 20 Jun 2013 09:19:48 -0400, Roy Smith wrote:
> In article
> <447dd1c6-1bb2-4276-a109-78d7a067b442@d8g2000pbe.googlegroups.com>,
> rusi <rustompmody@gmail.com> wrote:
>
>> > > def f(a, L=[]):
>> > > L.append(a)
>> > > return L
>
>> Every language has gotchas. This is one of python's.
>
> One of our pre-interview screening questions for Python programmers at
> Songza is about this. I haven't been keeping careful statistics, but
> I'd guess only about 50% of the candidates get this right.
What exactly is the question? Because it's not always a bug to use a
mutable default, there are good uses for it:
def func(arg, cache={}):
...
Now you can pass your own cache as an argument, otherwise the function
will use the default. The default cache is mutable, and so will remember
values from one invocation to the next.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-20 20:25 -0400 |
| Message-ID | <roy-AEF116.20253620062013@news.panix.com> |
| In reply to | #48829 |
In article <51c39b88$0$29999$c3e8da3$5496439d@news.astraweb.com>, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > On Thu, 20 Jun 2013 09:19:48 -0400, Roy Smith wrote: > > > In article > > <447dd1c6-1bb2-4276-a109-78d7a067b442@d8g2000pbe.googlegroups.com>, > > rusi <rustompmody@gmail.com> wrote: > > > >> > > def f(a, L=[]): > >> > > L.append(a) > >> > > return L > > > >> Every language has gotchas. This is one of python's. > > > > One of our pre-interview screening questions for Python programmers at > > Songza is about this. I haven't been keeping careful statistics, but > > I'd guess only about 50% of the candidates get this right. > > > What exactly is the question? Because it's not always a bug to use a > mutable default, there are good uses for it: It's a screening question; I'd rather not reveal all the details (it's really annoying when you find your screening questions posted to stack overflow). But, yes, I understand that there are good uses.
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-20 07:49 -0700 |
| Message-ID | <2e92b4c7-31be-40d2-a906-ab19f3630dfa@googlegroups.com> |
| In reply to | #48786 |
On Thursday, June 20, 2013 7:57:06 AM UTC-5, rusi wrote: > Every language has gotchas. This is one of python's. So are we purposely injecting illogic into our language just to be part of some "cool crowd" of programming languages with gotchas. "You thought intuitiveness was a virtue? Haha, we gotcha!" Or maybe this is reminiscent of the fraternity hazing rituals of days gone by: *POP* "Thank you Sir, may i have another?" > If you are a beginning python programmer, really the best > answer is: Just dont do it! Dont do what? Dont use > mutable arguments as function defaults. Once you cross the > noob stage you can check that its a standard gotcha: Just > run a search for 'python gotcha default []' > > And when you feel that you need to, use Steven's trick: > use a immutable indicator 'None' for the mutable []. Once > you cross the noob stage you can check that its a standard > gotcha: Just run a search for 'python gotcha default []' > Its even been discussed repeatedly on the python-ideas > list Your attempting to excuse an inexcusable language flaw by pointing out that the effects of the flaw can be avoided by using a workaround. And, to add insult to injury, you provide no good reason for the flaw to exist: "Just do x, y, and z and shut up. Yes we made a mistake but we are not about to admit our mistake and the onerous will be on all the noobs to re-invent the workaround each time" To me that is unacceptable. > Heres a correction suggestion: [...] Here's Terry Reedy's > nicely explaining the 'why-of-the-how' : [...] FWIW here > is a conceptual/philosophical explanation of your > confusion: There are 2 fundamental ways for approaching > the programming task -- functional and imperative. All these "explanations" ignore a fundamental fact about subroutines[1]. A call to a subroutine should exists as a unique transaction within the entire program. It is expected to optionally take inputs, and optionally return an output (depending on the definition). When the subroutine is completed, all inputs and local variables are expected to be destroyed. If the programmer wants a return value, he need simply ask. Data persistence is not a function of subroutines! Finally, a subroutine should never have side effects UNLESS the programmer explicitly ask for a side effect. However, the Python flaw of allowing mutable sequence arguments to persist between successive calls of a subroutine is breaking the entire definition of a subroutine, and for what noble purpose i ask? What purpose is SO important that you change a well established interface in a totally unintuitive manner? If your answer is that recursion is easier, then i say that is foolish because a programmer can keep a reference to a mutable sequence OUTSIDE the subroutine and you can save the "gotchas" for Guido's next birthday party. [1]: http://en.wikipedia.org/wiki/Subroutine
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-06-21 01:38 +1000 |
| Message-ID | <mailman.3627.1371742717.3114.python-list@python.org> |
| In reply to | #48796 |
On Fri, Jun 21, 2013 at 12:49 AM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> When the subroutine is completed, all inputs and local
> variables are expected to be destroyed. If the programmer
> wants a return value, he need simply ask. Data persistence
> is not a function of subroutines!
Funny, C violates your description too.
int counter()
{
static int count;
return ++count;
}
Function defaults in Python, being implemented as attributes on the
function object, are very similar in nature to static variables in C.
They're constructed once at function creation time, they're available
to that function (okay, C doesn't have any concept of "reaching into"
a function from the outside, Python does), they out-last any
particular execution of that function.
> Finally, a subroutine
> should never have side effects UNLESS the programmer
> explicitly ask for a side effect.
Bogus.
http://www.postgresql.org/docs/current/static/sql-createfunction.html
By default, a function is assumed to have side effects. The
programmer/sysadmin has to explicitly ask for PostgreSQL to treat the
function as NOT having side effects (the IMMUTABLE attribute, or
possibly its weaker cousin STABLE).
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-20 11:05 -0700 |
| Message-ID | <baf4de3c-e4ff-42c0-8d65-2f6cf825735c@googlegroups.com> |
| In reply to | #48802 |
On Thursday, June 20, 2013 10:38:34 AM UTC-5, Chris Angelico wrote: > Function defaults in Python, being implemented as > attributes on the function object, are very similar in > nature to static variables in C. Oh wait a minute. i think it's becoming clear to me now! Python functions are objects that take arguments, of which (the arguments) are then converted to attributes of the function object. Ah-Ha! Urm, but wait! We already have a method to define Objects. Heck, I can even create my own callable objects if i want! Observe: py> class FuncAdd(object): ... def __init__(self, ivalue): ... self.ivalue = ivalue ... def __call__(self, numeric): ... return self.ivalue + numeric ... py> fa = FuncAdd(10) py> fa(10) 20 py> fa(20) 30 I can even emulate (quite easily) this idea of "persistence of function arguments" with mutables too, Yippee! py> class ArgPersist(object): ... def __init__(self, lst): ... self.lst = lst ... def __call__(self, arg): ... self.lst.append(arg) ... return self.lst ... py> fp = ArgPersist([1,2,3]) py> fp(4) [1, 2, 3, 4] py> fp([5,6,7]) [1, 2, 3, 4, [5, 6, 7]] But then, i can even do it WITHOUT creating an object definition: py> mutable = [] py> def expandMutable(arg): ... mutable.append(arg) ... py> expandMutable(1) py> mutable [1] py> expandMutable([2,3,4]) py> mutable [1, [2, 3, 4]] ANY of those approaches are much less confusing than the current flaw and do not violate the least astonishment law.. I'm quite Okay with Python functions being first class objects, however, i am not okay with violating the fundamental nature of subroutines, especially when that violation can offer no clear and arguable benefits and is in fact unreasonably esoteric in nature.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-06-21 00:57 +0000 |
| Message-ID | <51c3a4f8$0$29999$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #48817 |
On Thu, 20 Jun 2013 11:05:32 -0700, Rick Johnson wrote:
> On Thursday, June 20, 2013 10:38:34 AM UTC-5, Chris Angelico wrote:
>> Function defaults in Python, being implemented as attributes on the
>> function object, are very similar in nature to static variables in C.
>
> Oh wait a minute. i think it's becoming clear to me now!
If only that were true, but I fear that you're just looking for an
argument.
> Python functions are objects that take arguments, of which (the
> arguments) are then converted to attributes of the function object.
Arguments in general are *not* converted to attributes. If you call a
function func(x=1, y=2), arguments 1 and 2 are not stored as attributes
anywhere. That would be silly, since 1 and 2 become local variables and
there is no point in storing them for later use since they don't get used
later.
Only default values for parameters are stored for later use. They have to
be stored *somewhere*, and Python chooses to store them as an attribute
of the function object, where they can be easily inspected, rather than
by storing them inside some undocumented and hidden location locked up in
a binary blob.
Even if Python chose late binding instead of early binding for function
defaults, the default would *still* need to be stored somewhere. The only
difference is that with early binding, the default value is calculated
once, and the object stored, while with late binding the default value is
re-calculated over and over again, every time it is needed, and a piece
of code that calculates the default value is stored.
> Ah-Ha! Urm, but wait! We already have a method to define Objects. Heck,
> I can even create my own callable objects if i want!
[snip]
Yes, you can create callable objects by defining a __call__ method.
That's okay. It is pure slander, invented by Perl programmers, that
Python gives you "only one way to do it". Python has functions for 99% of
your subroutine needs, and for more complex cases where your subroutine
needs to store permanent data and make them available to the caller, you
have class-based callables.
But really, using a class-based callable is a PITA. You have to define a
class, write an __init__ method, write a __call__ method, instantiate the
class, store the instance, and call it. 99% of the time a function will
do the job more easily, especially now that Python supports closures.
[...]
> But then, i can even do it WITHOUT creating an object definition:
>
> py> mutable = []
> py> def expandMutable(arg):
> ... mutable.append(arg)
> ...
[...]
The biggest, most obvious problem with the expandMutable approach is that
it relies on a global variable. I find it implausible that you, an
experienced programmer, is unaware of the dangers of global variables.
"Global variables considered harmful" has been a well-known principle of
programming dating back to the 1970s.
> ANY of those approaches are much less confusing than the current flaw
Confusing for whom? Beginners, who don't know the first thing about
Python? Programmers who are experienced with some other language but have
no clue about what these weird __init__ and __call__ methods do?
Programmers with 40 years experience who don't know anything about object-
oriented code? People who have been immersed in Python coding for 15
years? Every feature is confusing to *some* people and not others.
> and do not violate the least astonishment law..
That's a misuse of the Principle of Least Astonishment. Not just a
misuse, but in fact you've got it backwards: late binding of default
variables would violate the principle of least astonishment.
Python functions are created *once*, when defined. The cost of building
the function -- compiling the source code to byte code, assembling the
pieces into a function object, binding it to a name -- happens once and
once only, not every time you call the function. So it is reasonable to
expect that since the function is defined once, so are any default
arguments.
There are two obvious arguments against late binding: efficiency, and
consistency. Late binding is less efficient: if the code that defines the
default is expensive, you have to pay that cost once, that can't be
avoiding. But late binding makes you pay it again and again and again:
def f(arg, value=time.sleep(100)+5): # simulate an expensive default
...
I have no doubt that if Python recalculated the default every time, you
would be arguing that this is surprising and painful and that Python
ought to calculate the value once and cache it somewhere.
The other gotcha with late binding is that because the default is
recalculated each time, it can surprise you by changing unexpectedly:
def f(arg, value=x+5):
...
If the value of x changes, so does the value of the default. This may
surprise you. (It would certainly surprise me.)
> I'm quite Okay with
> Python functions being first class objects, however, i am not okay with
> violating the fundamental nature of subroutines,
In what way to Python functions violate the fundamental nature of
subroutines?
> especially when that
> violation can offer no clear and arguable benefits and is in fact
> unreasonably esoteric in nature.
Early binding offers clear benefits:
- consistency: the default cannot mysteriously change value due
to an unrelated change;
- efficiency: the default is calculated once, not over and over;
- it's easy to get late binding semantics starting with early
binding, but more difficult to go the other way.
- simplicity of implementation: late binding requires that
Python store, not the result of the expression, but the
expression itself (together with a context) for later
evaluation; early binding simply requires that the expression
is evaluated at runtime, like any other expression.
That's not to say that there are no arguments in favour of late binding.
But on balance, despite the odd sharp corner, I believe that early
binding's benefits far outweigh its gotchas.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-20 20:16 -0700 |
| Message-ID | <b1ef7774-b733-4d5c-85b3-dc1c5a8c4a3e@googlegroups.com> |
| In reply to | #48832 |
On Thursday, June 20, 2013 7:57:28 PM UTC-5, Steven D'Aprano wrote: > On Thu, 20 Jun 2013 11:05:32 -0700, Rick Johnson wrote: > > Python functions are objects that take arguments, of > > which (the arguments) are then converted to attributes > > of the function object. > Arguments in general are *not* converted to attributes. If > you call a function func(x=1, y=2), arguments 1 and 2 are > not stored as attributes anywhere. That would be silly, > since 1 and 2 become local variables and there is no point > in storing them for later use since they don't get used > later. Only default values for parameters are stored for > later use. Obviously you've lost the ability to recognize sarcasm. :( > They have to be stored *somewhere*, and Python chooses to > store them as an attribute of the function object, where > they can be easily inspected, rather than by storing them > inside some undocumented and hidden location locked up in > a binary blob. I like how that last sentence implicitly argues against an argument i never made, whilst explicitly supporting your argument. But, by all means Steven, proceed. > Even if Python chose late binding instead of early binding > for function defaults, the default would *still* need to > be stored somewhere. No, if your passing in a symbol, then the object it points to must exist *somewhere*. OTOH if your passing in a literal, or an expression, then the subroutine will need to "store" the resulting object. Yes. > The only difference is that with early binding, the > default value is calculated once, and the object stored, > while with late binding the default value is re-calculated > over and over again, every time it is needed, and a piece > of code that calculates the default value is stored. And that is *ONLY* the case using the currently broken system. You're arguing that the status-quo is better because the only alternative would be to re-evaluate the argument every time, when in fact, i provided three code examples that will not require re-evaluation of the mutable and i did so without sacrificing readability. Your argument is weak. > > Ah-Ha! Urm, but wait! We already have a method to define > > Objects. Heck, I can even create my own callable objects > > if i want! > > > [snip] > Yes, you can create callable objects by defining a > __call__ method. That's okay. It is pure slander, invented > by Perl programmers, that Python gives you "only one way > to do it". Python has functions for 99% of your subroutine > needs, and for more complex cases where your subroutine > needs to store permanent data and make them available to > the caller, you have class-based callables. But really, > using a class-based callable is a PITA. You have to define > a class, write an __init__ method, write a __call__ > method, instantiate the class, store the instance, and > call it. Mother of GOD call the authorities because a little girly man has been violated! That mean old Rick and his insistence on readability is causing a pandemic of carpal tunnel and PTSD syndrome. Haul him away, lock him up, and throw away the keys! Psst: That was sarcasm. > > But then, i can even do it WITHOUT creating an object > > definition: > > py> mutable = [] > > py> def expandMutable(arg): > > ... mutable.append(arg) > > ... > [...] > The biggest, most obvious problem with the expandMutable > approach is that it relies on a global variable. I find it > implausible that you, an experienced programmer, is > unaware of the dangers of global variables. I am quite aware of the dangers of globals, and i abhor their use in 99 percent of the cases. But we're talking about Python here *giggle*. The limits of a Python "global" are the module for which it is declared. Plus, this is quite amusing that you are now seemingly preferring the OOP style; how many times have you made snide remarks about my penchant for OOP? I dunno because i stopped counting after i ran out of fingers! Yes i can only count to ten, there, i beat you to the joke. Now we can focus again. > > ANY of those approaches are much less confusing than the > > current flaw > Confusing for whom? Beginners, who don't know the first > thing about Python? Of course programming noobs are going to be confused by this. > Programmers who are experienced with > some other language but have no clue about what these > weird __init__ and __call__ methods do? So now your going to argue that experienced programmers are going to intuit an IMPLICIT and unconventional subroutine data persistence, but they cannot intuit EXPLICIT words like "init" and "call"? Oh Please! > Programmers with > 40 years experience who don't know anything about object- > oriented code? Even those old dogs who refuse to use GUI's and code in the OOP style deserve a little more credit than you are giving them Steven. They might be dinosaurs but they're not stupid. Hardheaded, yes. Incapable of accepting change, yes. But stupid, no no no. > People who have been immersed in Python coding for 15 years? Well, if they are confused after 15 years i would suggest they take up a new profession. > Every feature is confusing to *some* people and not others. Indeed. But your not going win this argument by offering such generic postulations. Yes, noobs will be completely confused and experienced programmers from other languages will suffer a "WTF" moment, quickly followed by a: "Now i got to go RTFM because some cowboy designer decided to throw me a curve ball!!!" moment. When designing a language, intuitiveness should always be an important consideration, however, it need not be the ONLY consideration. There is no such thing an interface that will be intuitive to *everyone* on planet earth. But for this PyWart (and that's exactly what it is!) you're not only dealing with a violation of intuitiveness, your also dealing with a violation of fundamentals of subroutines; which has been established for many years across many languages. > > and do not violate the least astonishment law. > That's a misuse of the Principle of Least Astonishment. > Not just a misuse, but in fact you've got it backwards: > late binding of default variables would violate the > principle of least astonishment. Python functions are > created *once*, when defined. The cost of building the > function -- compiling the source code to byte code, > assembling the pieces into a function object, binding it > to a name -- happens once and once only, not every time > you call the function. So it is reasonable to expect that > since the function is defined once, so are any default > arguments. > Here you go again with this diversionary tactics! Of course the function is only compiled once! Anything else would be ludicrous. PAY ATTENTION! I'm not arguing that the damn function should be compiled each time it's called, no, i am arguing that each call to a subroutine should be a UNIQUE TRANSACTION. That means that no state can be carried from one transaction to another. > There are two obvious arguments against late binding: efficiency, and > consistency. Late binding is less efficient: if the code that defines the > default is expensive, you have to pay that cost once, that can't be > avoiding. But late binding makes you pay it again and again and again: > def f(arg, value=time.sleep(100)+5): # simulate an expensive default > ... You still don't understand what a TRANSACTION is do you? You would rather beat subroutines with a hammer until they resemble some pie in the sky, one size fits all *monstrosity* instead of taking a few seconds out of your precious time to creating a object to accomplish the same task. BamBam Says: "BamBam make square peg fit through round hole" *BAM* *BAM* Mom Says: Okay BamBam. Let's play nice please. > I have no doubt that if Python recalculated the default every time, you > would be arguing that this is surprising and painful and that Python > ought to calculate the value once and cache it somewhere. > The other gotcha with late binding is that because the default is > recalculated each time, it can surprise you by changing unexpectedly: > def f(arg, value=x+5): > ... > If the value of x changes, so does the value of the default. This may > surprise you. (It would certainly surprise me.) No Steven, because i wouldn't be foolish enough to write code like that. That looks like a disaster waiting to happen! But i must admit, i wish i could write bad code and then justify it on the bases that a flaw in the language is going to save me. Have you actually done this in reality? But more importantly, do you realize that there exist better ways? > > I'm quite Okay with Python functions being first class > > objects, however, i am not okay with violating the > > fundamental nature of subroutines, > In what way to Python functions violate the fundamental > nature of subroutines? If you expect me to type it out twice then you're in for a rude awaking. Next time, try reading my entire post. > > especially when that violation can offer no clear and > > arguable benefits and is in fact unreasonably esoteric > > in nature. > Early binding offers clear benefits: > - consistency: the default cannot mysteriously change value due > to an unrelated change; That's a solution to a problem only a fool would create. > - efficiency: the default is calculated once, not over and over; I prefer clear and readable code over obfuscation and magic. If i want to be astonished, i'll go watch David Copperfeild disappear an elephant, thank you very much.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-06-21 17:10 +1000 |
| Message-ID | <mailman.3655.1371798652.3114.python-list@python.org> |
| In reply to | #48843 |
On Fri, Jun 21, 2013 at 1:16 PM, Rick Johnson <rantingrickjohnson@gmail.com> wrote: > On Thursday, June 20, 2013 7:57:28 PM UTC-5, Steven D'Aprano wrote: >> Python functions are >> created *once*, when defined. The cost of building the >> function -- compiling the source code to byte code, >> assembling the pieces into a function object, binding it >> to a name -- happens once and once only, not every time >> you call the function. So it is reasonable to expect that >> since the function is defined once, so are any default >> arguments. >> > > Here you go again with this diversionary tactics! Of course > the function is only compiled once! Anything else would be > ludicrous. PAY ATTENTION! I'm not arguing that the damn > function should be compiled each time it's called, no, i am > arguing that each call to a subroutine should be a UNIQUE > TRANSACTION. That means that no state can be carried from > one transaction to another. Why should that be? Why is a subroutine not allowed to retain any state? You're free to write code in a purely functional style if you like - all objects must be immutable, all functions must have no side effects and simply return a value. That's not the only way to code, and it is *definitely* not a rule to be codified into Python. One of Python's strengths is that it permits many styles of programming, without shoehorning every programmer and every task into one model. Of course, RickPy 4000 is welcome to enforce all these sorts of inane rules if it likes. I shan't be using it if it does. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-21 07:32 -0700 |
| Message-ID | <f7ec7e3d-fbc2-4e5d-a38b-adcaedd12a09@googlegroups.com> |
| In reply to | #48847 |
On Friday, June 21, 2013 2:10:49 AM UTC-5, Chris Angelico wrote: > Why should that be? Why is a subroutine not allowed to > retain any state? I refuse to repeat myself for lazy readers! > You're free to write code in a purely functional style if > you like I don't want to write code in a purely functional style, i find that style too restricting. > all objects must be immutable, That would suck! > all functions must have no side effects and simply return > a value. No thanks! > One of Python's strengths is that it permits many styles > of programming, without shoehorning every programmer and > every task into one model. Yes, and i consider that aspect of Python a virtue. But this "persistence of mutable arguments" is not a virtue, it's an abomination!
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-06-21 16:22 +0000 |
| Message-ID | <51c47db9$0$29999$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #48843 |
On Thu, 20 Jun 2013 20:16:19 -0700, Rick Johnson wrote:
> On Thursday, June 20, 2013 7:57:28 PM UTC-5, Steven D'Aprano wrote:
>> On Thu, 20 Jun 2013 11:05:32 -0700, Rick Johnson wrote:
>> They [default argument values] have to be stored *somewhere*, and
>> Python chooses to store them as an attribute of the function object,
>> where they can be easily inspected, rather than by storing them inside
>> some undocumented and hidden location locked up in a binary blob.
>
> I like how that last sentence implicitly argues against an argument i
> never made, whilst explicitly supporting your argument.
You're overly defensive. I never said, or even suggested, that you argued
the opposite. I simply state a fact: any language with default arguments
must store the default argument somewhere. In a language with early
binding of default arguments, the *value itself* must be stored. In a
language with late binding, *the expression that generates that value*
(sometimes called a "thunk") must be stored.
The consequence of this fact is that if you wish to argue that functions
have no business storing state, then you're arguing that functions must
not have default arguments.
[...]
>> Even if Python chose late binding instead of early binding for function
>> defaults, the default would *still* need to be stored somewhere.
>
> No, if your passing in a symbol, then the object it points to must exist
> *somewhere*. OTOH if your passing in a literal, or an expression, then
> the subroutine will need to "store" the resulting object. Yes.
Passing in a symbol? I'm afraid I don't understand you. Do you mean a
name? Something like:
def func(x=y):
...
A single name, like 'y' above, is an expression. In any case, while the
name must exist at the time the function is defined, it does not need to
exist when the function is called:
py> y = 23
py> def func(x=y):
... return x
...
py> del y
py> func()
23
>> The only difference is that with early binding, the default value is
>> calculated once, and the object stored, while with late binding the
>> default value is re-calculated over and over again, every time it is
>> needed, and a piece of code that calculates the default value is
>> stored.
>
> And that is *ONLY* the case using the currently broken system.
No. You have failed to understand. ANY language that offers default
values for function parameters must operate under the same limitation.
The language must store either the default value itself, or some
executable expression that generates that default value.
Even if your language doesn't offer default values, all this means is
that the responsibility for doing this is moved away from the compiler to
you. For instance, if your languages offers an "is_undefined" function,
you can manually store the default value in a global variable and then
retrieve it when needed:
# Store function state in a global variable.
default := [];
def func(x):
if is_undefined(x):
{
x := default;
}
...
That suffers the *exact same gotcha* as Python if the default value is
mutable.
Or you can store the state in a callable class, what C++ calls a functor:
class MyClass:
# Store function state in a class member.
default := [];
def __call__(this, x):
if is_undefined(x):
{
x := this.default;
}
...
This too suffers the *exact same gotcha* as Python if the default is
mutable. Storing the function state as an instance member instead of a
class member doesn't save you; the same applies.
There are only three ways to avoid the mutable default gotcha:
* Prohibit default arguments, and don't provide an is_undefined
test. All function arguments *must* be supplied explicitly by
the caller, like in Pascal.
* Use late-binding and re-calculate the default every time it is
needed. This risks being expensive, and has its own share of
gotchas.
* If you can somehow determine which values are mutable and which
are not, you might allow default arguments only for immutable
values. Some restrictive languages can do this: Java, with it's
strongly enforced rules for "private" and "protected" members,
and compile-time checks, may be able to do something like this.
And purely functional languages like Haskell simply avoid the
issue by ensuring that *all* values are immutable. But for
Python, it is impossible.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2013-06-21 15:57 +0000 |
| Message-ID | <51c477dd$0$29999$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #48817 |
On Thu, 20 Jun 2013 11:05:32 -0700, Rick Johnson wrote:
> Python functions are objects that take arguments, of which (the
> arguments) are then converted to attributes of the function object.
> Ah-Ha! Urm, but wait! We already have a method to define Objects. Heck,
> I can even create my own callable objects if i want!
>
> Observe:
> py> class FuncAdd(object):
> ... def __init__(self, ivalue):
> ... self.ivalue = ivalue
Notice how you are storing state here? I thought you said, and I quote:
"When the subroutine is completed, ALL INPUTS and local variables are
expected to be destroyed. If the programmer wants a return value, he need
simply ask. Data persistence is NOT a function of subroutines!"
[emphasis added]
And yet here you are defining persistent input ("ivalue") to the callable
subroutine, which is stored as external state and not destroyed at the
end of the subroutine call:
> ... def __call__(self, numeric):
> ... return self.ivalue + numeric
> ...
All you have done here is define a subroutine with state, precisely the
thing that you say subroutines must never have. What you haven't done is
define a function which takes a default value that can be overridden when
called. Your argument is invalid.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-21 10:01 -0700 |
| Message-ID | <565a1c8f-6fd9-4bab-9834-076eaea527f8@googlegroups.com> |
| In reply to | #48867 |
On Friday, June 21, 2013 10:57:17 AM UTC-5, Steven D'Aprano wrote:
> On Thu, 20 Jun 2013 11:05:32 -0700, Rick Johnson wrote:
> > py> class FuncAdd(object):
> > ... def __init__(self, ivalue):
> > ... self.ivalue = ivalue
> Notice how you are storing state here? I thought you said,
> and I quote: "When the subroutine is completed, ALL INPUTS
> and local variables are expected to be destroyed. If the
> programmer wants a return value, he need simply ask. Data
> persistence is NOT a function of subroutines!"
> [emphasis added]
>
> And yet here you are defining persistent input ("ivalue")
> to the callable subroutine, which is stored as external
> state and not destroyed at the end of the subroutine call:
Because Steven, my dear lad, what i created is NOT a
subroutine, no, it's an object that stores state and is
callable. Each call to the object is merely a request to
mutate and then return it's current state. A subroutine, at
least REAL subroutines (not the snake oil that Python is
selling) do not have state.
Real subroutines merely:
1. Optionally take inputs
2. Execute a body of code (which could have side effects,
but which is NOT persistent!)
3. Optionally return output
That's it. If your problem requires state persistence, then
you need to move up to an Object definition. Use the correct
tool for the job dammit!
> > ... def __call__(self, numeric):
> > ... return self.ivalue + numeric
> > ...
> All you have done here is define a subroutine with state,
> precisely the thing that you say subroutines must never
> have.
It's Okay to carry state EXPLICITLY, it's NOT okay to carry
state IMPLICITLY. My implementation is correct, Python's is
not.
Besides, encapsulated state is one of the fundamental
principles of OOP programming, along with interfaces; and
i've satisfied both! The mutable is protected from the world
by an object, and the object allows manipulation of the
mutable via an interface.
But unlike Python's limited implementation, my approach is
scalable. I can change the interface, i can add more
functionality, i can do anything i want.
"I am the Lizard King, and i can do, well ANYTHING!"
However, with Python's limited approach, i'm just a slave to
the implementation. I'm forced to follow estoeric rules with
no chance of scalability.
########################################################
# Moral of the Day #
########################################################
# You should only use SUBROUTINES for executing #
# subprograms requiring stateless transactions. #
# Alternativly, subprograms requiring persistant state #
# transactions should wield the power of a custom #
# object defintion -- or you can use the #
# global+subroutine method if encapsulation is not #
# warrented. #
########################################################
But in any case, following this advice will ensure less bugs
and more maintainable code than Python's current
implementation of lunacy.
> What you haven't done is define a function which takes a
> default value that can be overridden when called.
Oh, you mean like this?
py> class Func(object):
... def __call__(self, arg=0):
... print(arg)
...
py> f = Func()
py> f("pwned")
pwned
> Your argument is invalid.
My argument is not invalid, i just figured i did not need
wipe your bum for you, "Homer". ~(_8^(I)
[toc] | [prev] | [next] | [standalone]
| From | Rotwang <sg552@hotmail.co.uk> |
|---|---|
| Date | 2013-06-21 18:47 +0100 |
| Message-ID | <kq23at$i39$1@dont-email.me> |
| In reply to | #48870 |
On 21/06/2013 18:01, Rick Johnson wrote: > > [stuff] It isn't clear to me from your posts what exactly you're proposing as an alternative to the way Python's default argument binding works. In your version of Python, what exactly would happen when I passed a mutable argument as a default value in a def statement? E.g. this: >>> a = [1, 2, 3] >>> a.append(a) >>> b = object() >>> def f(x = [None, b, [a, [4]]]): ... pass # do something What would you like to see the interpreter do in this case?
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-21 11:26 -0700 |
| Message-ID | <7e1ed740-df18-4978-b11d-8ca9c4b5bd04@googlegroups.com> |
| In reply to | #48871 |
On Friday, June 21, 2013 12:47:56 PM UTC-5, Rotwang wrote:
> It isn't clear to me from your posts what exactly you're
> proposing as an alternative to the way Python's default
> argument binding works. In your version of Python, what
> exactly would happen when I passed a mutable argument as a
> default value in a def statement? E.g. this:
>
> >>> a = [1, 2, 3]
> >>> a.append(a)
> >>> b = object()
> >>> def f(x = [None, b, [a, [4]]]):
> ... pass # do something
>
> What would you like to see the interpreter do in this case?
Ignoring that this is a completely contrived example that has
no use in the real world, here are one of three methods by
which i can handle this:
============================================================
The Benevolent Approach:
============================================================
I could cast a "virtual net" over my poor lemmings before
they jump off the cliff by throwing an exception:
Traceback (most recent screw-up last):
Line BLAH in SCRIPT
def f(x = [None, b, [a, [4]]]):
ArgumentError: No mutable default arguments allowed!
============================================================
The Apathetic Approach:
============================================================
I could just assume that a programmer is responsible for the
code he writes. If he passes mutables into a function as
default arguments, and then mutates the mutable later, too
bad, he'll understand the value of writing solid code after
a few trips to exception Hell.
============================================================
The Malevolent Approach (disguised as beneva-loon-icy):
============================================================
I could use early binding to confuse the hell out of him and
enjoy the laughs with all my ivory tower buddies as he falls
into fits of confusion and rage. Then enjoy again when he
reads the docs. Ahh, the gift that just keeps on giving!
============================================================
Conclusion:
============================================================
As you can probably guess the malevolent approach has some
nice fringe benefits.
You know, out of all these post, not one of you guys has
presented a valid use-case that will give validity to the
existence of this PyWart -- at least not one that CANNOT be
reproduced by using my fine examples. All you can muster is
some weak argument about protecting the lemmings.
Is anyone up the challenge?
Does anyone here have any real chops?
PS: I won't be holding my breath.
[toc] | [prev] | [next] | [standalone]
Page 1 of 5 [1] 2 3 4 5 Next page →
Back to top | Article view | comp.lang.python
csiph-web