Re: [Tutor] Output reason

2019-07-12 Thread Mats Wichmann
On 7/12/19 11:39 AM, Alan Gauld via Tutor wrote:
> On 12/07/2019 15:24, Gursimran Maken wrote:
> 
>> Can someone please explain me the reason for below output.
> 
> You've been bitten by one of the most common gotchas in Python :-)
> 
>> def fun(n,li = []):
>> a = list(range(5))
>> li.append(a)
>> print(li)
>>
>> fun(4)
>> fun(5,[7,8,9])
>> fun(4,[7,8,9])
>> fun(5) # reason for output (why am I getting to values in this output.)
> 
> When you define a default value in Python it creates the default value
> at the time you define the function. It then uses that value each time a
> default is needed. in the case of a list that means Python creates an
> empty list and stores it for use as the default.

It may help in seeing why this happens to be aware that a def: statement
is an executable statement like any other, which is executed at the time
it is reached in the file.  Running it generates a function object, a
reference to it being attached to the name of the function. Conceptually,

def foo():

is like

foo = FunctionConstructor()

foo ends up referring to an object that is marked as callable so you can
then later call it as foo().  So it makes some sense that some things
have to happen at object construction time, like setting up the things
that are to be used as defaults.


> When you first call the function with the default Python adds values to
> the defaiult list.
> 
> Second time you call the function using the default Python adds (more)
> values to (the same) default list.

FWIW, Python does the same no matter the type of the default argument,
but it only causes the trap we poor programmers fall into if the type is
one that can be modified ("mutable").  If you have fun(n, a=5) or fun(n,
s="stringystuff") those are unchangeable and we don't get this little
surprise.


By the way, checker tools (and IDEs/editors with embedded checking
capabilities) will warn about this, which is a hint on using good tools.
 pylint would tell you this:

W0102: Dangerous default value [] as argument (dangerous-default-value)
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Output reason

2019-07-12 Thread Richard Damon
If I remember how that works right, there is a single empty list that is 
created and used for all the calls that use the default argument, and then your 
function modifies that empty list so it is no longer empty, and that modified 
list is used on future calls. (Not good to use a mutable as a default 
parameter).

A better solution would be to make the default something like None, and test if 
at the beginning of the function li is None, and if so set it to an empty list, 
and that empty list will be in function scope so it goes away and a new one is 
created on a new call.

> On Jul 12, 2019, at 10:24 AM, Gursimran Maken  
> wrote:
> 
> Hi,
> 
> Can someone please explain me the reason for below output.
> 
> Program:
> def fun(n,li = []):
>a = list(range(5))
>li.append(a)
>print(li)
> 
> fun(4)
> fun(5,[7,8,9])
> fun(4,[7,8,9])
> fun(5) # reason for output (why am I getting to values in this output.)
> 
> Output:
> [[0, 1, 2, 3, 4]]
> [7, 8, 9, [0, 1, 2, 3, 4]]
> [7, 8, 9, [0, 1, 2, 3, 4]]
> [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
> 
> Thank you,
> Gursimran
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Output reason

2019-07-12 Thread Alan Gauld via Tutor
On 12/07/2019 15:24, Gursimran Maken wrote:

> Can someone please explain me the reason for below output.

You've been bitten by one of the most common gotchas in Python :-)

> def fun(n,li = []):
> a = list(range(5))
> li.append(a)
> print(li)
> 
> fun(4)
> fun(5,[7,8,9])
> fun(4,[7,8,9])
> fun(5) # reason for output (why am I getting to values in this output.)

When you define a default value in Python it creates the default value
at the time you define the function. It then uses that value each time a
default is needed. in the case of a list that means Python creates an
empty list and stores it for use as the default.

When you first call the function with the default Python adds values to
the defaiult list.

Second time you call the function using the default Python adds (more)
values to (the same) default list.

Sometimes that is useful, usually it's not. The normal pattern to get
round this is to use a None default and modify the function like so

def fun(n,li = None):
if not ni: ni = []   # create new list
a = list(range(5))
li.append(a)
return li  # bad practice to mix logic and display...

HTH

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Output reason

2019-07-12 Thread Gursimran Maken
Hi,

Can someone please explain me the reason for below output.

Program:
def fun(n,li = []):
a = list(range(5))
li.append(a)
print(li)

fun(4)
fun(5,[7,8,9])
fun(4,[7,8,9])
fun(5) # reason for output (why am I getting to values in this output.)

Output:
[[0, 1, 2, 3, 4]]
[7, 8, 9, [0, 1, 2, 3, 4]]
[7, 8, 9, [0, 1, 2, 3, 4]]
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

Thank you,
Gursimran
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor