Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Default Value (http://www.velocityreviews.com/forums/t961939-default-value.html)

Ahmed Abdulshafy 06-19-2013 07:17 PM

Default Value
 
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?

Jussi Piitulainen 06-19-2013 07:35 PM

Re: Default Value
 
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.

Rick Johnson 06-19-2013 07:38 PM

Re: Default Value
 
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/Princip...t_astonishment


Gary Herron 06-19-2013 07:57 PM

Re: Default Value
 
On 06/19/2013 12:17 PM, 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


This code:
> def f(a, L=[]):
> L.append(a)
> return L


does the same as this code:

M=[]
def f(a, L=M):
L.append(a)
return L

where it's slightly more obvious that the list is created once, and
modified with each call to the function (or rather with each call to the
function that does not supply its own value for L).

Gary Herron


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



--
Dr. Gary Herron
Department of Computer Science
DigiPen Institute of Technology
(425) 895-4418


Steven D'Aprano 06-20-2013 01:17 AM

Re: Default Value
 
On Wed, 19 Jun 2013 12:17:35 -0700, 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?


"How" is easy: it is stored inside the function object, where the code
can get to it. To be precise, in the function object's __defaults__
attribute:

py> def f(a=1, b=5, c="hello world"):
.... pass
....
py> f.__defaults__
(1, 5, 'hello world')


"Why" is even easier: because the creator of Python decided to do it this
way.

This is called "early binding" -- the default value is bound (assigned)
to the parameter early in the process, when the function is created. This
has a few advantages:

- It is the most efficient: the cost of evaluating the defaults
only happens once, when the function is created, not over and
over again, every time the function is called.

- It is usually what people expect. If you have a function with
a default, you normally expect the default to be set once, and
not re-evaluated each time.

- If you start with "early binding", it is trivial to get "late
binding" semantics instead; but if you start with late binding,
it's less convenient to get early binding semantics.

The usual way to get the effect of late binding in Python is with a
sentinel value to trigger the re-evaluation of the default. Normally, we
would use None and a call-time check:

def function(arg, value=None):
if value is None:
# Re-calculate the default.
value = ...
# rest of code



--
Steven

rusi 06-20-2013 12:57 PM

Re: Default Value
 
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/Princip...t_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/pyt...ry/000073.html
Here's Terry Reedy's nicely explaining the 'why-of-the-how' :
http://mail.python.org/pipermail/pyt...ay/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_winner...us_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/articl...tractions.html

And you've had a little excess of the FP koolaid read :
http://blog.languager.org/2012/08/fu...osophical.html

Roy Smith 06-20-2013 01:19 PM

Re: Default Value
 
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.

rusi 06-20-2013 01:31 PM

Re: Default Value
 
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/transc...xx/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 :-)

Rick Johnson 06-20-2013 02:49 PM

Re: Default Value
 
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

Chris Angelico 06-20-2013 03:38 PM

Re: Default Value
 
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/curre...efunction.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


All times are GMT. The time now is 11:16 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.