Hello All,
Why is python designed so that b and c (according to code below)
actually share the same list object? It seems more natural to me that
each object would be created with a new list object in the points
variable.
class Blob:
def __init__(self, points=[]):
self._points = points
b = Blob()
c = Blob()
b._points.appen d(1)
c._points.appen d(2)
print b._points
# this will show that b._points is the same object as c._points 35 1975
Rick Giuly <rg**********@y ahoo.comwrites:
Hello All,
Hello,
Why is python designed so that b and c (according to code below)
actually share the same list object? It seems more natural to me that
each object would be created with a new list object in the points
variable.
class Blob:
def __init__(self, points=[]):
self._points = points
b = Blob()
c = Blob()
b._points.appen d(1)
c._points.appen d(2)
print b._points
# this will show that b._points is the same object as c._points
This is probably the MFAQ (Most FAQ)!
Have a look in http://www.python.org/doc/faq/ (I can't point at the
question as my internet pipes to the US are very rusty this morning)
HTH
--
Arnaud
On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
Hello All,
Why is python designed so that b and c (according to code below)
actually share the same list object? It seems more natural to me that
each object would be created with a new list object in the points
variable.
That's not natural *at all*. You're initialising the argument "points"
with the same list every time. If you wanted it to have a different list
each time, you should have said so. Don't blame the language for doing
exactly what you told it to do.
class Blob:
def __init__(self, points=[]):
self._points = points
Let's analyze this. You create a method __init__. That function is
created *once*. As part of the process of creating the function, the
argument "points" is given the default value of an empty list. The
creation of that empty list happens *once*, when the method is created.
In the body of the function, you set the _points attribute to points.
Naturally it is the same list object.
Since the method is only created once, it is only natural that the
default value is also only created once. If you want something to be
created each time the function is called, you have to put it inside the
body of the function:
class Blob:
def __init__(self, points=None):
if points is None:
points = []
self._points = points
Now you will have _points set to a unique empty list each time.
This is no different from doing this:
alist = []
b1 = Blob(alist)
b2 = Blob(alist)
Would you be surprised that b1 and b2 share the same list? If yes, then
you need to think about how Python really works, rather than how you
imagine it works.
--
Steven
On Nov 15, 3:40*am, Rick Giuly <rgiuly.gr...@y ahoo.comwrote:
Hello All,
Why is python designed so that b and c (according to code below)
actually share the same list object? It seems more natural to me that
each object would be created with a new list object in the points
variable.
class Blob:
* * def __init__(self, points=[]):
* * * * self._points = points
b = Blob()
c = Blob()
b._points.appen d(1)
c._points.appen d(2)
print b._points
# this will show that b._points is the same object as c._points
Hi Rick,
I don't think Dennis or Steven read your post very well. You said
'Why does Python do X?', and 'It seems natural to you to do not X'.
Dennis and Steven both said, 'Python does X'.
Steven did get around to suggesting an answer though. He said:
If you want something to be
created each time the function is called, you have to put it inside the
body of the function:
Taking this to be true, the answer to your question is, 'Because the
object isn't created inside the body of the function,' or, 'Because
the argument list is outside the body of the function'.
From your post, it's hard to tell whether this 'duh'-type observation
would point out the salient feature of the construct, or whether
you're after something deeper.
If you're asking, 'Why isn't the argument list considered to be inside
the body?', then the answer is, it's pretty much arbitrary.
Regardless of which one the author of Python chose, the other's
workaround would be equally short, and neither one is obviously
indicated by the syntax.
And until someone sends you a link to Python's author's blog that
gives the answer, 'To make creating static variables really easy',
don't let them tell you so.
On Sat, 15 Nov 2008 21:29:22 -0800, Aaron Brady wrote:
I don't think Dennis or Steven read your post very well.
It's possible.
You said 'Why
does Python do X?', and 'It seems natural to you to do not X'. Dennis
and Steven both said, 'Python does X'.
I also disputed that it is natural to do not-X (runtime creation of
default arguments), and explained why such an interpretation doesn't
match with the way Python operates. I admit I didn't answer the "why"
part.
Steven did get around to suggesting an answer though. He said:
>If you want something to be created each time the function is called, you have to put it inside the body of the function:
If you want to be pedantic, then my "answer" (which you seem to approve
of) doesn't correspond to either of the original poster's questions. If
you're going to be pedantic, then be pedantic all the way, and criticize
me for answering a question that wasn't asked :-P
Taking this to be true, the answer to your question is, 'Because the
object isn't created inside the body of the function,' or, 'Because the
argument list is outside the body of the function'.
Actually, the correct answer to "Why?" would be "Because that's the
decision Guido van Rossum made back in the early 1990s when he first
started designing Python". That of course leads to the obvious question
"Why did he make that decision?", and the answer to that is:
* it leads to far more efficient performance when calling functions;
E.g. if the default value is expensive to calculate, it is better to
calculate it once, when the function is created, than every single time
the function is called.
Additionally, the effbot once mentioned in a similar thread that there
are real performance benefits in the Python VM from binding the default
value once only. I don't know the exact details of that, but I trust
Fredrik knows what he's talking about.
* it has less scope for surprise when calling functions.
E.g. I would argue that most people would be surprised, and dismayed, if
this code fails:
x = 1
def foo(a, b=x):
return a+b
del x
print foo(2)
From your post, it's hard to tell whether this 'duh'-type observation
would point out the salient feature of the construct, or whether you're
after something deeper.
If you're asking, 'Why isn't the argument list considered to be inside
the body?', then the answer is, it's pretty much arbitrary.
No, it is not an arbitrary choice. I've given practical reasons why the
Python choice is better. If you want default argument to be created from
scratch when the function is called, you can get it with little
inconvenience, but the opposite isn't true. It is very difficult to get
static default arguments given a hypothetical Python where default
arguments are created from scratch. There's no simple, easy idiom that
will work. The best I can come up with is a convention:
# Please don't change this, or strange things will happen.
_private = ResultOfExpensi veCalculation()
def foo(a, b=_private):
return a+b
The above is still vulnerable to code accidentally over-writing _private
with some other value, or deleting it, but at least we avoid the
expensive calculation every time.
Or possibly:
def foo(a, b=foo._private) :
return a+b
foo._private = ResultOfExpensi veCalculation()
which has obvious disadvantages with regard to shadowing, renaming,
anonymous functions, and so forth.
Regardless
of which one the author of Python chose, the other's workaround would be
equally short,
Not true. One has an obvious workaround, the other only has a *partial*
workaround.
and neither one is obviously indicated by the syntax.
I would disagree, but not enough to argue.
--
Steven
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com .auwrites:
On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
>Hello All,
Why is python designed so that b and c (according to code below) actually share the same list object? It seems more natural to me that each object would be created with a new list object in the points variable.
That's not natural *at all*. You're initialising the argument "points"
with the same list every time. If you wanted it to have a different list
each time, you should have said so. Don't blame the language for doing
exactly what you told it to do.
Come on. The fact that this questions comes up so often (twice in 24h)
is proof that this is a surprising behaviour. I do think it is the
correct one but it is very natural to assume that when you write
def foo(bar=[]):
bar.append(6)
...
you are describing what happens when you _call_ foo, i.e.:
1. if bar is not provided, make it equal to []
2. Append 6 to bar
3. ...
--
Arnaud
On Nov 16, 2:05*am, Arnaud Delobelle <arno...@google mail.comwrote:
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com .auwrites:
On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
Hello All,
Why is python designed so that b and c (according to code below)
actually share the same list object? It seems more natural to me that
each object would be created with a new list object in the points
variable.
That's not natural *at all*. You're initialising the argument "points"
with the same list every time. If you wanted it to have a different list
each time, you should have said so. Don't blame the language for doing
exactly what you told it to do.
Come on. *The fact that this questions comes up so often (twice in 24h)
is proof that this is a surprising behaviour. *I do think it is the
correct one but it is very natural to assume that when you write
* * def foo(bar=[]):
* * * * *bar.append(6)
* * * * *...
you are describing what happens when you _call_ foo, i.e.:
* * 1. if bar is not provided, make it equal to []
* * 2. Append 6 to bar
* * 3. ...
+1. Understanding and accepting the current behavior (mainly because
of the extra performance penalty of evaluating the default expressions
on every call would incur) is one thing, claiming that it is somehow
natural is plain silly, as dozens of threads keep showing time and
time again. For better or for worse the current semantics will
probably stay forever but I wish Python grows at least a syntax to
make the expected semantics easier to express, something like:
def foo(bar=`[]`):
bar.append(6)
where `expr` would mean "evaluate the expression in the function
body". Apart from the obvious usage for mutable objects, an added
benefit would be to have default arguments that depend on previous
arguments:
def foo(x, y=`x*x`, z=`x+y`):
return x+y+z
as opposed to the more verbose and less obvious current hack:
def foo(x, y=None, z=None):
if y is None: y = x*x
if z is None: z = x+y
return x+y+z
George
On Sun, 16 Nov 2008 07:05:51 +0000, Arnaud Delobelle wrote:
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com .auwrites:
>On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
>>Hello All,
Why is python designed so that b and c (according to code below) actually share the same list object? It seems more natural to me that each object would be created with a new list object in the points variable.
That's not natural *at all*. You're initialising the argument "points" with the same list every time. If you wanted it to have a different list each time, you should have said so. Don't blame the language for doing exactly what you told it to do.
Come on. The fact that this questions comes up so often (twice in 24h)
is proof that this is a surprising behaviour.
Of course it's surprising. People make an assumption based on other
languages. But there is nothing "natural" about that assumption. It may
be common, but that doesn't mean it's the only way to think about it.
If you check the archives of this newsgroup, you will see that some time
not very long ago I made the suggestion that perhaps Python should raise
a warning when it creates a function with an obviously mutable default
argument. In practice, that would mean checking for three special cases:
[], {} and set(). So I'm sympathetic towards the surprise people feel,
but I don't agree that it is natural. "Natural" is a thought-stopper.
It's meant to imply that any other alternative is unnatural, crazy,
stupid, perverted, or whatever other alternative to natural you prefer,
therefore stop all disagreement.
I do think it is the
correct one but it is very natural to assume that when you write
def foo(bar=[]):
bar.append(6)
...
you are describing what happens when you _call_ foo, i.e.:
1. if bar is not provided, make it equal to []
2. Append 6 to bar
3. ...
Which is *exactly* what happens -- except of course once you append six
to the list [], it now looks like [6].
Why assume that "make it equal to []" implies a different list every
time, rather than that it is a specific list that happens to start off as
[]? Why isn't it equally "natural" to assume that it's the same list each
time, and it starts off as [] but need not stay that way?
--
Steven
George Sakkis wrote:
On Nov 16, 2:05 am, Arnaud Delobelle <arno...@google mail.comwrote:
>Steven D'Aprano <st...@REMOVE-THIS-cybersource.com .auwrites:
>>On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote: Hello All, Why is python designed so that b and c (according to code below) actually share the same list object? It seems more natural to me that each object would be created with a new list object in the points variable. That's not natural *at all*. You're initialising the argument "points" with the same list every time. If you wanted it to have a different list each time, you should have said so. Don't blame the language for doing exactly what you told it to do.
Come on. The fact that this questions comes up so often (twice in 24h) is proof that this is a surprising behaviour. I do think it is the correct one but it is very natural to assume that when you write
def foo(bar=[]): bar.append(6) ...
you are describing what happens when you _call_ foo, i.e.:
1. if bar is not provided, make it equal to [] 2. Append 6 to bar 3. ...
+1. Understanding and accepting the current behavior (mainly because
of the extra performance penalty of evaluating the default expressions
on every call would incur) is one thing, claiming that it is somehow
natural is plain silly, as dozens of threads keep showing time and
time again. For better or for worse the current semantics will
probably stay forever but I wish Python grows at least a syntax to
make the expected semantics easier to express, something like:
def foo(bar=`[]`):
bar.append(6)
where `expr` would mean "evaluate the expression in the function
body". Apart from the obvious usage for mutable objects, an added
benefit would be to have default arguments that depend on previous
arguments:
Would you also retain the context surrounding the function declaration
so it's obvious how it will be evaluated, or would you limit the default
values to expressions with no bound variables?
def foo(x, y=`x*x`, z=`x+y`):
return x+y+z
as opposed to the more verbose and less obvious current hack:
def foo(x, y=None, z=None):
if y is None: y = x*x
if z is None: z = x+y
return x+y+z
"Less obvious" is entirely in the mind of the reader. However I can see
far more justification for the behavior Python currently exhibits than
the semantic time-bomb you are proposing.
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Dennis Lee Bieber wrote:
On Sat, 15 Nov 2008 01:40:04 -0800 (PST), Rick Giuly
<rg**********@y ahoo.comdeclaim ed the following in comp.lang.pytho n:
>Why is python designed so that b and c (according to code below) actually share the same list object? It seems more natural to me that each object would be created with a new list object in the points variable.
This is a FAQ... default arguments are evaluation only ONCE, during
the "compilatio n" of the function.
>class Blob: def __init__(self, points=[]): self._points = points
The preferred/recommended form is to use (very explicit, one test,
one "assignment ")
def __init__(self, points=None):
if points:
self._points = points
else:
self._points = []
or (shorter; one test, potentially two "assignment s")
def __init__(self, points=None):
if not points: points = []
self._points = points
I hesitate to beat the thoroughly obvious to death with a stick, but
this is a *very* bad way to make the test. If you are using None as a
sentinel to indicate that no argument was provided to the call then the
correct test is
if points is None:
points = []
The code shown fails to distinguish between passing an empty list and
not passing an argument at all.
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/ This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Rane Bowen |
last post by:
Hi,
I am using python with a makepy generated wrapper on a COM application. One
of this object's methods has 3 parameters, two of which are optional.
If I call the method with just the non-optional parameter, or all three
parameters, it works. If I call it with the first two parameters, I get the
following error:
(-2147352567, 'Exception occurred.', (0, 'Amphora.Session.1', 'A bad
parameter was passed to the method', None, 0,...
|
by: JT |
last post by:
how can i declare a function that will accept an optional parameter?
something like:
function newFunc(strValue1, strValue2) --where strValue2 is optional.
thanks much.
|
by: spammy |
last post by:
Hi all,
Im attempting to use a COM class in C# via .NET interop. The class has two
modes - synhrounous and asynchronous. The mode is determined by the use (or
not) of an optional out parameter:
COMClass test = new COMClass();
object results = null;
|
by: Otto Wyss |
last post by:
I've the following function declaration:
wxTree GetLastChild (const wxTree& item, long& cookie) const;
I'd like to make the cookie parameter optional, i.e. "long& cookie =
....", without breaking any software using the old API. The
implementation looks like
wxTree wxTreeListMainWindow::GetLastChild (const wxTree& item,
long& cookie) const {
|
by: William Ryan |
last post by:
I just picked up a copy of John Robbins' debugging book and started to look
at disassembled code. Anyway, I hate optional Parameters in VB, but I was
checking them out to see what IL is created. I've done this before with
Modules, and saw that <gasp> they behave just like sealed classes with only
static members.
Anyway, it looks like Optional Parameters are nothing but a way to tell the
compiler to write some overloads for you. So, in...
| |
by: Yong Jiang |
last post by:
I am trying to convert some vb code calling COM oboject
methods to C#. Example shown as follows
Dim Stream As New ADODB.Stream
Call Stream.Open()
Stream.Open has three optional parameters. I am trying to
convert it to C# as shown as follows
ADODB.Stream Stream = null;
|
by: Hanover |
last post by:
In at typical SQL command if I want an optional parameter, I say
"Where ID=@ID or @ID=Null"
This way if I dont pass in a parameter, it will just pull all of the
IDs.
Is there a way to set this up in the text command of a SQLCommand
object in .NET?
|
by: Oenone |
last post by:
In our applications, we use the special value of DateTime.MinValue to
represent "null dates" throughout all our code. We recently ran into an
issue where we wanted an optional date parameter for a procedure. We weren't
able to declare it with DateTime.MinValue as its default value, as MinValue
is a read-only property rather than a constant. To work around, we had to
use a "magic date" that we checked for later on. I was never very happy...
|
by: Sam Shrefler |
last post by:
I'm working on creating a WebService / WebMethod to receive a record
in real time from another system. The record contains about 20
fields. 10 of which aren't required.
I was planning on just making a method with 20 parameters. But, I see
there is no way to make an "optional" c# parameter. I was just
wondering if anyone had an suggestions on how to implement this? The
parameters are all different primitive types (int, string,...
|
by: =?Utf-8?B?V2ViQnVpbGRlcjQ1MQ==?= |
last post by:
I'll ask, how do you do it?
--
(i''ll be asking a lot of these, but I find C# totally way cooler than vb
and there''s no go''n back!!!)
thanks (as always)
kes
|
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,...
| |
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...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |