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


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

Beginner Question

Started byMarcin Rak <mrak@sightlineinnovation.com>
First post2016-06-01 17:55 -0700
Last post2016-06-02 11:02 -0700
Articles 8 — 5 participants

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


Contents

  Beginner Question Marcin Rak <mrak@sightlineinnovation.com> - 2016-06-01 17:55 -0700
    Re: Beginner Question boB Stepp <robertvstepp@gmail.com> - 2016-06-01 20:42 -0500
      Re: Beginner Question Marcin Rak <mrak@sightlineinnovation.com> - 2016-06-02 06:10 -0700
    Re: Beginner Question Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-06-02 13:53 +1000
    Re: Beginner Question Igor Korot <ikorot01@gmail.com> - 2016-06-02 00:21 -0400
      Re: Beginner Question Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-06-02 15:20 +1000
        Re: Beginner Question Igor Korot <ikorot01@gmail.com> - 2016-06-02 09:38 -0400
          Re: Beginner Question sohcahtoa82@gmail.com - 2016-06-02 11:02 -0700

#109325 — Beginner Question

FromMarcin Rak <mrak@sightlineinnovation.com>
Date2016-06-01 17:55 -0700
SubjectBeginner Question
Message-ID<ea789a85-a90c-4ff8-ab34-4b6dc1fc6c2f@googlegroups.com>
Hi to all

I have a beginner question to which I have not found an answer I was able to understand.  Could someone explain why the following program:

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

print(f(1))
print(f(2))
print(f(3))

gives us the following result:

[1]
[1,2]
[1,2,3]

How can this be, if we never catch the returned L when we call it, and we never pass it on back to f???

Any help is appreciated.
Marcin

[toc] | [next] | [standalone]


#109326

FromboB Stepp <robertvstepp@gmail.com>
Date2016-06-01 20:42 -0500
Message-ID<mailman.74.1464831757.1839.python-list@python.org>
In reply to#109325
On Wed, Jun 1, 2016 at 7:55 PM, Marcin Rak <mrak@sightlineinnovation.com> wrote:
> Hi to all
>
> I have a beginner question to which I have not found an answer I was able to understand.  Could someone explain why the following program:
>
> def f(a, L=[]):
>     L.append(a)
>     return L
>
> print(f(1))
> print(f(2))
> print(f(3))
>
> gives us the following result:
>
> [1]
> [1,2]
> [1,2,3]
>
> How can this be, if we never catch the returned L when we call it, and we never pass it on back to f???

This comes up rather frequently.  In fact, if you just copy your
function (Which is used in the official Python tutuorial.) and paste
it into Google you will get some relevant hits.  One such is:

https://pythonconquerstheuniverse.wordpress.com/category/python-gotchas/

As the link will explain the behavior you observe is a consequence of
two things:  When Python assigns the default argument for the empty
list and that lists are *mutable*.

Enjoy!


-- 
boB

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


#109364

FromMarcin Rak <mrak@sightlineinnovation.com>
Date2016-06-02 06:10 -0700
Message-ID<c21138aa-7400-4d4d-90f6-2b834afe9d9d@googlegroups.com>
In reply to#109326
That linked help clear up my confusion...yes you really have to know how things work internally to understand why things happen the way they happen.

Thanks again to all

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


#109331

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2016-06-02 13:53 +1000
Message-ID<574fadda$0$22141$c3e8da3$5496439d@news.astraweb.com>
In reply to#109325
On Thursday 02 June 2016 10:55, Marcin Rak wrote:

> Hi to all
> 
> I have a beginner question to which I have not found an answer I was able to
> understand.  Could someone explain why the following program:
> 
> def f(a, L=[]):
>     L.append(a)
>     return L


The default value is set once, and once only, so you get the same list each 
time, not a new empty list.

Default values in Python are sort of like this:

HIDDEN_DEFAULT_VALUE = []  # initialised once
def f(a, L):
    if L is not defined:
        L = HIDDEN_DEFAULT_VALUE
    L.append(a)
    return L


except that HIDDEN_DEFAULT_VALUE is not actually a global variable. Every 
function gets its own storage for defaults. The technical term for this is 
"early binding of default values".

If you want to get a new, fresh list each time ("late binding of default 
values") you should use a sentinel value:


def f(a, L=None):
    if L is None:
        L = []  # new, fresh list each time
    L.append(a)
    return L




-- 
Steve

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


#109332

FromIgor Korot <ikorot01@gmail.com>
Date2016-06-02 00:21 -0400
Message-ID<mailman.75.1464841301.1839.python-list@python.org>
In reply to#109325
Hi, guys,

On Wed, Jun 1, 2016 at 9:42 PM, boB Stepp <robertvstepp@gmail.com> wrote:
> On Wed, Jun 1, 2016 at 7:55 PM, Marcin Rak <mrak@sightlineinnovation.com> wrote:
>> Hi to all
>>
>> I have a beginner question to which I have not found an answer I was able to understand.  Could someone explain why the following program:
>>
>> def f(a, L=[]):
>>     L.append(a)
>>     return L
>>
>> print(f(1))
>> print(f(2))
>> print(f(3))
>>
>> gives us the following result:
>>
>> [1]
>> [1,2]
>> [1,2,3]
>>
>> How can this be, if we never catch the returned L when we call it, and we never pass it on back to f???

I think the OP question here is:

Why it is printing the array?
There is no line like:

t = f(1)
print t

So, why the first print does print the list? The return value should
be thrown away...

Thank you.

>
> This comes up rather frequently.  In fact, if you just copy your
> function (Which is used in the official Python tutuorial.) and paste
> it into Google you will get some relevant hits.  One such is:
>
> https://pythonconquerstheuniverse.wordpress.com/category/python-gotchas/
>
> As the link will explain the behavior you observe is a consequence of
> two things:  When Python assigns the default argument for the empty
> list and that lists are *mutable*.
>
> Enjoy!
>
>
> --
> boB
> --
> https://mail.python.org/mailman/listinfo/python-list

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


#109333

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2016-06-02 15:20 +1000
Message-ID<574fc214$0$1585$c3e8da3$5496439d@news.astraweb.com>
In reply to#109332
On Thursday 02 June 2016 14:21, Igor Korot wrote:

> Hi, guys,
> 
> On Wed, Jun 1, 2016 at 9:42 PM, boB Stepp <robertvstepp@gmail.com> wrote:
>> On Wed, Jun 1, 2016 at 7:55 PM, Marcin Rak <mrak@sightlineinnovation.com>
>> wrote:
>>> Hi to all
>>>
>>> I have a beginner question to which I have not found an answer I was able
>>> to understand.  Could someone explain why the following program:
>>>
>>> def f(a, L=[]):
>>>     L.append(a)
>>>     return L
>>>
>>> print(f(1))
>>> print(f(2))
>>> print(f(3))
>>>
>>> gives us the following result:
>>>
>>> [1]
>>> [1,2]
>>> [1,2,3]
>>>
>>> How can this be, if we never catch the returned L when we call it, and we
>>> never pass it on back to f???
> 
> I think the OP question here is:
> 
> Why it is printing the array?

Because he calls the function, then prints the return result.

print(f(1))

calls f(1), which returns [1], then prints [1].

Then he calls:

print(f(2))

which returns [1, 2] (but he expects [2]), then prints it. And so on.


> There is no line like:
> 
> t = f(1)
> print t

Correct. But there are lines:

print(f(1))
print(f(2))
print(f(3))



-- 
Steve

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


#109366

FromIgor Korot <ikorot01@gmail.com>
Date2016-06-02 09:38 -0400
Message-ID<mailman.93.1464874721.1839.python-list@python.org>
In reply to#109333
Steven,

On Thu, Jun 2, 2016 at 1:20 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Thursday 02 June 2016 14:21, Igor Korot wrote:
>
>> Hi, guys,
>>
>> On Wed, Jun 1, 2016 at 9:42 PM, boB Stepp <robertvstepp@gmail.com> wrote:
>>> On Wed, Jun 1, 2016 at 7:55 PM, Marcin Rak <mrak@sightlineinnovation.com>
>>> wrote:
>>>> Hi to all
>>>>
>>>> I have a beginner question to which I have not found an answer I was able
>>>> to understand.  Could someone explain why the following program:
>>>>
>>>> def f(a, L=[]):
>>>>     L.append(a)
>>>>     return L
>>>>
>>>> print(f(1))
>>>> print(f(2))
>>>> print(f(3))
>>>>
>>>> gives us the following result:
>>>>
>>>> [1]
>>>> [1,2]
>>>> [1,2,3]
>>>>
>>>> How can this be, if we never catch the returned L when we call it, and we
>>>> never pass it on back to f???
>>
>> I think the OP question here is:
>>
>> Why it is printing the array?
>
> Because he calls the function, then prints the return result.
>
> print(f(1))
>
> calls f(1), which returns [1], then prints [1].
>
> Then he calls:
>
> print(f(2))
>
> which returns [1, 2] (but he expects [2]), then prints it. And so on.
>
>
>> There is no line like:
>>
>> t = f(1)
>> print t
>
> Correct. But there are lines:
>
> print(f(1))
> print(f(2))
> print(f(3))

I think you missed the point.

Compare:

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

print(f(1))
print(f(2))
print(f(3))

vs.

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

t = f(1)
print t
t = f(2)
print t
t = f(3)
print t

For people that comes from C/C++/Java, the first syntax is kind of weird:
you return a value from the function but the caller does not save it anywhere.
Especially since the return is not a basic type and most of them are
not familiar
with scalar vs list context (sorry for the Perl terminology here)

Thank you.


>
>
>
> --
> Steve
>
> --
> https://mail.python.org/mailman/listinfo/python-list

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


#109377

Fromsohcahtoa82@gmail.com
Date2016-06-02 11:02 -0700
Message-ID<a3166686-72e6-401b-9347-46c8417ba81b@googlegroups.com>
In reply to#109366
On Thursday, June 2, 2016 at 6:38:56 AM UTC-7, Igor Korot wrote:
> Steven,
> 
> On Thu, Jun 2, 2016 at 1:20 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> > On Thursday 02 June 2016 14:21, Igor Korot wrote:
> >
> >> Hi, guys,
> >>
> >> On Wed, Jun 1, 2016 at 9:42 PM, boB Stepp <robertvstepp@gmail.com> wrote:
> >>> On Wed, Jun 1, 2016 at 7:55 PM, Marcin Rak <mrak@sightlineinnovation.com>
> >>> wrote:
> >>>> Hi to all
> >>>>
> >>>> I have a beginner question to which I have not found an answer I was able
> >>>> to understand.  Could someone explain why the following program:
> >>>>
> >>>> def f(a, L=[]):
> >>>>     L.append(a)
> >>>>     return L
> >>>>
> >>>> print(f(1))
> >>>> print(f(2))
> >>>> print(f(3))
> >>>>
> >>>> gives us the following result:
> >>>>
> >>>> [1]
> >>>> [1,2]
> >>>> [1,2,3]
> >>>>
> >>>> How can this be, if we never catch the returned L when we call it, and we
> >>>> never pass it on back to f???
> >>
> >> I think the OP question here is:
> >>
> >> Why it is printing the array?
> >
> > Because he calls the function, then prints the return result.
> >
> > print(f(1))
> >
> > calls f(1), which returns [1], then prints [1].
> >
> > Then he calls:
> >
> > print(f(2))
> >
> > which returns [1, 2] (but he expects [2]), then prints it. And so on.
> >
> >
> >> There is no line like:
> >>
> >> t = f(1)
> >> print t
> >
> > Correct. But there are lines:
> >
> > print(f(1))
> > print(f(2))
> > print(f(3))
> 
> I think you missed the point.
> 
> Compare:
> 
> def f(a, L=[]):
>      L.append(a)
>      return L
> 
> print(f(1))
> print(f(2))
> print(f(3))
> 
> vs.
> 
> def f(a, L=[]):
>      L.append(a)
>      return L
> 
> t = f(1)
> print t
> t = f(2)
> print t
> t = f(3)
> print t
> 
> For people that comes from C/C++/Java, the first syntax is kind of weird:
> you return a value from the function but the caller does not save it anywhere.
> Especially since the return is not a basic type and most of them are
> not familiar
> with scalar vs list context (sorry for the Perl terminology here)
> 
> Thank you.
> 
> 
> >
> >
> >
> > --
> > Steve
> >
> > --
> > https://mail.python.org/mailman/listinfo/python-list

I came from C/C++/Java, and the first syntax makes perfect sense to me.  You're just taking the result of a function and directly passing it as a parameter to another.  There's nothing confusing about that.  C/C++/Java let you do it.

[toc] | [prev] | [standalone]


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


csiph-web