473,699 Members | 2,383 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Empty list as default parameter

Hello all,

Maybe I'm being foolish, but I just don't understand why the following
code behaves as it does:

- = - = - = -

class listHolder:
def __init__( self, myList=[] ):
self.myList = myList

def __repr__( self ): return str( self.myList )

# debug: 'a' should contain 42, 'b' should be empty. But no.
a = listHolder()
a.myList.append ( 42 )
b = listHolder()
print a
print b

- = - = - = -

I was expecting to see [42] then [], but instead I see [42] then [42]. It
seems that a and b share a reference to the same list object. Why?

--
<<<Alexspudro s Potatopoulos>>>
Defender of Spudkind

Jul 18 '05 #1
26 15560
Alex Panayotopoulos wrote:
Hello all,

Maybe I'm being foolish, but I just don't understand why the following
code behaves as it does:

- = - = - = -

class listHolder:
def __init__( self, myList=[] ):
self.myList = myList

def __repr__( self ): return str( self.myList )

# debug: 'a' should contain 42, 'b' should be empty. But no.
a = listHolder()
a.myList.append ( 42 )
b = listHolder()
print a
print b

- = - = - = -

I was expecting to see [42] then [], but instead I see [42] then [42]. It
seems that a and b share a reference to the same list object. Why?


Really common mistake: lists are _mutable_ objects and self.myList
references the same object as the default parameter. Therefore
a.myList.append modifies default value as well. Mutable defaults are
better avoided (except for some variants of memo pattern). Standard
trick is:

def __init__(self, myList = None):
if myList is None:
self.myList = []
else:
self.myList = myList

regards,
anton.

Jul 18 '05 #2
>
class listHolder:
def __init__( self, myList=[] ):
self.myList = myList

def __repr__( self ): return str( self.myList )

# debug: 'a' should contain 42, 'b' should be empty. But no.
a = listHolder()
a.myList.append ( 42 )
b = listHolder()
print a
print b

- = - = - = -

I was expecting to see [42] then [], but instead I see [42] then [42]. It
seems that a and b share a reference to the same list object. Why?


Hi,
AFAIK, the default parameter values are only instantiated once. So, the
default-myList is always the same object. The coding above should be
rewritten like...

class listHolder:
def __init__( self, myList=None ):
if myList = None:
self.myList = []
else:
self.myList = myList

Regards,
Thorsten


Jul 18 '05 #3
Alex Panayotopoulos wrote:
Maybe I'm being foolish, but I just don't understand why the following
code behaves as it does:

- = - = - = -

class listHolder:
def __init__( self, myList=[] ):
self.myList = myList

def __repr__( self ): return str( self.myList )

# debug: 'a' should contain 42, 'b' should be empty. But no.
a = listHolder()
a.myList.append ( 42 )
b = listHolder()
print a
print b

- = - = - = -

I was expecting to see [42] then [], but instead I see [42] then [42]. It
seems that a and b share a reference to the same list object. Why?


the default value expression is evaluated once, when the function
object is created, and the resulting object is bound to the argument.

if you want to create a new object on every call, you have to do
that yourself:

def __init__( self, myList=None):
if myList is None:
myList = [] # create a new list
self.myList = myList

or perhaps:

def __init__( self, myList=None):
self.myList = myList or []

see the description of the "def" statement for more info:

http://www.python.org/doc/current/ref/function.html

</F>


Jul 18 '05 #4
On Fri, 21 Nov 2003, anton muhin wrote:
Really common mistake: lists are _mutable_ objects and self.myList
references the same object as the default parameter. Therefore
a.myList.append modifies default value as well.
It does?!
Ah, I've found it: listHolder.__in it__.func_defau lts

Hmm... this behaviour is *very* counter-intuitive. I expect that if I were
to define a default to an explicit object...

def process_tree1( start=rootNode )

....then I should indeed be able to process rootNode through manipulating
start. However, if I define a default as a new instance of an object...

def process_tree2( myTree=tree() )

....then the function should, IMHO, create a new object every time it is
entered. (By having func_defaults point to tree.__init__, or summat.)

Was there any reason that this sort of behaviour was not implemented?
Mutable defaults are better avoided (except for some variants of memo
pattern). Standard trick is:

def __init__(self, myList = None):
if myList is None:
self.myList = []
else:
self.myList = myList


Thank you. I shall use this in my code. (Although I would have preferred a
trick that uses less lines!)

--
<<<Alexspudro s Potatopoulos>>>
Defender of Spudkind

Jul 18 '05 #5
Alex Panayotopoulos wrote:
On Fri, 21 Nov 2003, anton muhin wrote:
Was there any reason that this sort of behaviour was not implemented?

It was discussed several times (search for it, if you're interested),
but I don't remeber details.
Mutable defaults are better avoided (except for some variants of memo
pattern). Standard trick is:

def __init__(self, myList = None):
if myList is None:
self.myList = []
else:
self.myList = myList

Thank you. I shall use this in my code. (Although I would have preferred a
trick that uses less lines!)


if you wish a one-linear, somehting like this might work:
self.myList = myList or []

regards,
anton.

Jul 18 '05 #6
Alex Panayotopoulos wrote on Fri, 21 Nov 2003 13:26:13 +0000:

<snip>
Hmm... this behaviour is *very* counter-intuitive. I expect that if I were
to define a default to an explicit object...


I think so too. It's documented as a Python pitfall. Here are some more:
http://zephyrfalcon.org/labs/python_pitfalls.html
def __init__(self, myList = None):
if myList is None:
self.myList = []
else:
self.myList = myList


Thank you. I shall use this in my code. (Although I would have preferred a
trick that uses less lines!)


You could use the quasi-ternary trick:
mylist = None
(mylist is None and [[]] or [mylist])[0] [] mylist = []
(mylist is None and [[]] or [mylist])[0] [] mylist = [3,4]
(mylist is None and [[]] or [mylist])[0]

[3, 4]

Not that big an improvement really :).

--
Yours,

Andrei

=====
Mail address in header catches spam. Real contact info (decode with rot13):
ce******@jnanqb b.ay. Fcnz-serr! Cyrnfr qb abg hfr va choyvp cbfgf. V ernq
gur yvfg, fb gurer'f ab arrq gb PP.
Jul 18 '05 #7
Alex Panayotopoulos <A.************ **@sms.ed.ac.uk > wrote:
On Fri, 21 Nov 2003, anton muhin wrote:
Really common mistake: lists are _mutable_ objects and self.myList
references the same object as the default parameter. Therefore
a.myList.append modifies default value as well.


It does?!
Ah, I've found it: listHolder.__in it__.func_defau lts

Hmm... this behaviour is *very* counter-intuitive. I expect that if I were
to define a default to an explicit object...

def process_tree1( start=rootNode )

...then I should indeed be able to process rootNode through manipulating
start. However, if I define a default as a new instance of an object...

def process_tree2( myTree=tree() )

...then the function should, IMHO, create a new object every time it is
entered. (By having func_defaults point to tree.__init__, or summat.)

Was there any reason that this sort of behaviour was not implemented?


The reason for this behavior lies in the fact that Python is an
interpreted language, and that the class and def keywords are actually
considered statements. One creates a class object with a certain name,
the other creates a function object with a certain name. The def (or
class) statement is executed as soon as the entire function code or
class code has been parsed -- in other words, as soon as the interpreter
drops out of the indentation block of the def or class statement.
Therefore, any default values passed to function arguments in a def
statement will be evaluated once and only once, when the def statement
is executed.

Look at this, for example:
n = 5
def f(x = n):
return x
n = 3

print n # Prints 3
print f() # Prints 5

Note that the default argument to f() is the value of n when the def
statement was executed, not the value of n when f() is called.

--
Robin Munn
rm***@pobox.com
Jul 18 '05 #8
Alex Panayotopoulos fed this fish to the penguins on Friday 21 November
2003 05:26 am:


Was there any reason that this sort of behaviour was not implemented?
Because, to be simplistic, the def statement is not a declaration, it
is an executable statement. Execution of def results in the generation
of a function object, which requires evaluating argument definitions.
Execution of def occurs /once/, during the initial load of the
module/file.

This is much different from things like old BASICs, where calling a
function causes the interpreter to rescan the source file to find the
function declaration.

Others can explain it much better.

-- =============== =============== =============== =============== == <
wl*****@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
=============== =============== =============== =============== == <
Bestiaria Home Page: http://www.beastie.dm.net/ <
Home Page: http://www.dm.net/~wulfraed/ <


Jul 18 '05 #9
anton muhin wrote:
Alex Panayotopoulos wrote:
On Fri, 21 Nov 2003, anton muhin wrote:
Was there any reason that this sort of behaviour was not implemented?

It was discussed several times (search for it, if you're interested),
but I don't remeber details.
Mutable defaults are better avoided (except for some variants of memo
pattern). Standard trick is:

def __init__(self, myList = None):
if myList is None:
self.myList = []
else:
self.myList = myList

Thank you. I shall use this in my code. (Although I would have preferred
a trick that uses less lines!)


if you wish a one-linear, somehting like this might work:
self.myList = myList or []


This is dangerous, don't do it.
None or "just a marker" 'just a marker'

seems to work. But:
[] or "just a marker"

'just a marker'

I. e. your one-liner will create a new list when the myList argument is not
provided or is provided and bound to an empty list.

Peter
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

49
2608
by: Mark Hahn | last post by:
As we are addressing the "warts" in Python to be fixed in Prothon, we have come upon the mutable default parameter problem. For those unfamiliar with the problem, it can be seen in this Prothon code sample where newbies expect the two function calls below to both print : def f( list= ): print list.append!(1) f() # prints
3
1636
by: Dave Opstad | last post by:
I fully understand why this happens: ---------------------------- >>> a = , , , , ] >>> b = ] * 5 >>> a , , , , ] >>> b , , , , ] >>> a == b
12
12700
by: earl | last post by:
class temp { public: temp(); foo(char, char, char*); private: char matrix; }; temp::foo(char p, char o, char m = matrix )
59
8793
by: Steve R. Hastings | last post by:
So, Python 2.5 will have new any() and all() functions. http://www.python.org/dev/peps/pep-0356/ any(seq) returns True if any value in seq evaluates true, False otherwise. all(seq) returns True if all values in seq evaluate true, False otherwise. I have a question: what should these functions return when seq is an empty list?
11
2340
by: Matthias Pfeifer | last post by:
Hi there, I am trying to declare a function that takes a std::list<parameter. I want this function to have an empty list as a default parameter. It's a template function also. Currently i am stuck because my compiler does not find a matching function when i do a call. here is my code: // ############## code begins
1
1409
by: Tzury Bar Yochay | last post by:
while I can invoke methods of empty string '' right in typing (''.join(), etc.) I can't do the same with empty list example: I would not use b = a since I don't want changes on 'b' to apply on 'a'
6
1460
by: s0suk3 | last post by:
I wanted to know if there's any way to create a method that takes a default parameter, and that parameter's default value is the return value of another method of the same class. For example: class A: def __init__(self): self.x = 1 def meth1(self): return self.x
0
973
by: Alexnb | last post by:
Okay this is a simple question I just don't know how. If I have a list, say: funList = and after a while something possible should have been appended to it, but wasn't. How can I test if that list is empty. -- View this message in context: http://www.nabble.com/Testing-for-an-empty-list-tp18268092p18268092.html Sent from the Python - python-list mailing list archive at Nabble.com.
2
1935
by: Matthew Fitzgibbons | last post by:
Alexnb wrote: if not funList: do_something() -Matt
0
8615
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9174
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8914
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8883
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7750
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6534
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4376
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3057
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2009
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.