Finding the instance reference of an object

S

Steven D'Aprano

Since Python only has one parameter passing mechanism, there's no need
to give it a name at all. If you're having to explain it, just explain
it, and don't bother naming it!

This would make sense if Python was the only computer language in
existence, but it isn't. Consequently people who know these other
languages come along and ask "So is Python call by value or call by
reference?".

The correct answer to that is "No", but unfortunately there are far too
many people who refuse to accept the existence of any third parameter
passing mechanism and therefore confuse the issue by hammering the round
peg of Python's calling mechanism into the square hole of their pre-
conceptions. Depending on those particular pre-conceptions, they will
insist that Python "clearly and obviously is call by reference", or that
it is "clearly and obviously call by value, where the values are
references".
 
B

Bruno Desthuilliers

greg a écrit :
I didn't use the phrase "value of variable x" anywhere in my
definitions, so it doesn't matter what it means, or even
whether it means anything at all.
>

There you go, getting distracted by that annoying word
"value". Forget about it, we don't need it!

Err... So what does "call by value" means if "values" doesn't mean
anything ?-)
 
S

Steven D'Aprano

But that's only true in languages where *assigning* a large array will
also copy the entire array.

Maybe, maybe not. To be consistent, it should be true. But how do you
know if a language you are unfamiliar with is consistent?

In any case, to somebody only familiar with the classical value-vs-
reference model, Python seems rather inconsistent:


x = 1
y = x # does assignment make copies?
y += 1
assert x == 1
=> succeeds, which implies that Python makes a copy when assigning

x = [1]
y = x # does assignment make copies?
y += [1]
assert x == [1]
=> fails, which implies that Python uses references when assigning

Hence you get people who argue that Python does call-by-value for numbers
and call-by-reference for lists -- and yes, I've seen people make that
exact argument.

The reality is that Python isn't inconsistent, it merely seems to be if
you assume it is some other language. Python actually treats numbers and
lists identically.

When people discover that Python's behaviour doesn't fall neatly into
their preconceived notions of c-b-v and c-b-r, there are two ways of
dealing with that:

(1) Accept that perhaps there's at least one more way of doing assignment
and parameter passing.

(2) Or jump through hoops trying to force how Python works to somehow
match your preconceptions.


This does not happen in Python, therefore
there is no reason to suppose that it will happen when passed as a
parameter.

Of course there is a reason: we've been told that Python is call by
value, and call by value implies that a copy is made when you pass it to
a function. The fact that many programmers already have an idea of what
they think c-b-v implies is what makes calling Python c-b-v such a
pernicious mistake. If you want to call Python "call by ginger" I won't
object, because most people have no preconceived ideas of what call by
ginger means and therefore won't be lured into incorrect assumptions
about Python.

Before you can understand parameter passing, whether by-value or
by-reference, you first have to understand how assignment works *in the
language concerned*, not some other language you happen to know
previously.

It's certainly true that the baggage people bring from their previous
languages can sometimes be a serious barrier, but that especially happens
when folk insist on using the same terminology to describe different
things.

For example, to somebody coming to Python from Lisp or Scheme, the word
"list" carries particular connotations. It's unfortunate that Python
lists are not like Lisp lists, but we're stuck with that now, and besides
there's only so many good names for a list-like array, and whatever name
was chosen would trip up somebody. Another example, augmented assignment
in Python trips up C programmers, because x += y looks the same but
behaves differently than x += y in C.

There's enough difficulty with learning a new programming language
without people adding to it by misusing terms like "call by value" to
describe what Python does.
 
S

Steven D'Aprano

Nonsense.

Maybe I missed this part. What does the phrase, "value of variable x"
mean in Python? Is it the same as what it means in C, Pascal, etc.?

In other words,
x= [ 2, 3, 4 ]
'0x%x'%id( x )
'0xb39dd0'

What is the value of 'x'?
a) [ 2, 3, 4 ]
b) An object with contents [ 2, 3, 4 ]
c) 0xb39dd0
d) None of the above.

Solution a) is just shorthand for b), because there are (or at least
could be) many such objects [2, 3, 4]. So I'd accept either a) or b) as
reasonable answers.

Solution c) is the answer that is required for "Python is call-by-value"
to be correct.

If "value of 'x'" is not defined, we should agree on a definition that's
really clear and useful, favoring useful.

The ordinary dictionary meaning is sufficient: "what is denoted by a
symbol".

After that's established, we
can proceed to evaluating what 'call by value' would behave like, which
would then determine if Python behaves like it.

Call by value is traditionally defined in at least some languages as
meaning that a copy of the value of the parameter is passed to the
function. Those languages include C and Pascal, and possibly Basic. I'd
estimate that 80% of programmers over the last 40 years have had their
understanding of "call by whatever" shaped by those three languages.

So, logically, if... she... weighs... the same as a duck,... she's made
of wood.

Nice one :)
 
A

Arnaud Delobelle

On Oct 31, 9:12 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
[...]
There's enough difficulty with learning a new programming language
without people adding to it by misusing terms like "call by value" to
describe what Python does.

Maybe it could be named 'call by assignment'?

Then the focus might shift towards misconceptions about assignment and
augmented assignment, which are more often than not at the root of
people's misunderstandings.
 
D

Dale Roberts

Since Python only has one parameter passing mechanism,
there's no need to give it a name at all. If you're
having to explain it, just explain it, and don't
bother naming it!

Since Python only has one parameter passing mechanism,
there's no need to give it a name at all. If you're
having to explain it, just explain it, and don't
bother naming it!

But then why bother having any other names at all for other languages
that have only one calling mechanism, like Call By Name, Call By Macro
Expansion, etc.

If it is a different process, it needs a different name. OR, as you
suggest, no name at all, just an explanation.

But please don't give it the WRONG name!
 
D

Dale Roberts

Call by reference is not an "idiom", it's a *language
feature*.
...
You can use an idiom in C to get the same effect, but this
is not the same thing as the language having it as a feature.

Okay, I'll grant that, but is there a language other than Python that
uses the Call By Value feature that does not do it by assigning/
copying the result of an expression into the formal parameter?

The terms "result" and "value" are generally understood to refer to
the working data of the program, not the internal workings of the
interpreter, VM, or compiler.

So, yes, internally the C Python runtime does use Call By Value. It's
written in C after all - that's all it can do.

But Call By Value is not a feature of the Python language.

dale

[Somebody unplug my network cable! I can't stop!]
 
P

pjacobi.de

Instead of comparing integers:
x = 1
y = x # does assignment make copies?
y += 1
assert x == 1
=> succeeds, which implies that Python makes a copy when assigning

with lists:
x = [1]
y = x # does assignment make copies?
y += [1]
assert x == [1]
=> fails, which implies that Python uses references when assigning

Compare lists with tupels:

x = (1,)
y = x # does assignment make copies?
y += (1,)
assert x == (1,)
=> succeeds, which implies *what*?

Regards,
Peter
 
D

Douglas Alan

greg said:
I didn't mean that these are the only two parameter passing
mechanisms in existence -- I know there are others.

I don't follow you. You stated that once you understand how
assignment works, you understand the calling mechanism. That's just
not true. Algol, for instance, did assignment-by-value but
call-by-name.
If you told me they use "assignment by sharing", that would tell me
a lot *more* about the language than just talking about parameter
passing.

Not really. Call-by-sharing virtually implies that the language does
assignment-by-sharing. (I know of no counter-examples, and it is
difficult to see how a violation of this rule-of-thumb would be useful
in any new language.) Stating that a language does
assignment-by-sharing does not imply that it does call-by-sharing. Or
at least not exclusively so. Cf. certain dialects of Lisp. Also C#,
which supports a variety of argument passing strategies.

|>oug
 
S

Steven D'Aprano

Instead of comparing integers:
x = 1
y = x # does assignment make copies? y += 1
assert x == 1
=> succeeds, which implies that Python makes a copy when assigning

with lists:
x = [1]
y = x # does assignment make copies? y += [1]
assert x == [1]
=> fails, which implies that Python uses references when assigning

Compare lists with tupels:

x = (1,)
y = x # does assignment make copies? y += (1,)
assert x == (1,)
=> succeeds, which implies *what*?


To somebody who is stuck in the traditional mentality of "call by
reference" versus "call by value", it implies that Python copies tuples
and ints (and strings, and frozensets) but not lists (and dicts and sets
and class instances).

They would be wrong, but when you start with faulty assumptions that is
often the case. The assumption that there are only two calling
conventions is such a pernicious assumption. Look at how many thousands
of words have been spent trying to get Joe to understand that c-by-r and
c-b-v are not the only two options, and that what Python does is not
either c-b-r or c-b-v.
 
S

Steven D'Aprano

x = 1
y = x # does assignment make copies? y += 1
assert x == 1
=> succeeds, which implies that Python makes a copy when assigning

with lists:
x = [1]
y = x # does assignment make copies? y += [1]
assert x == [1]
=> fails, which implies that Python uses references when assigning

Compare lists with tupels:

x = (1,)
y = x # does assignment make copies? y += (1,)
assert x == (1,)
=> succeeds, which implies *what*?

All any of this does is 'implies that += may create a new object or may
mutate an existing object. RTFM: Python Reference Manual 6.3.1

The exact test isn't important. If you don't like those tests, replace
them with something else: y = y + [1] perhaps, or y.sort(), or whatever
you like. Naturally you will get different results according to whatever
specific test you try, and the interpretation of those results will
therefore be different. But no matter what tests are done, somebody who
fails to understand Python's calling model (or if you prefer, its
assignment model) will wrongly interpret the results they see in terms of
a model they do understand.

Because call by reference and call by value are such older and
established models, and used in such historically popular languages like
C and Pascal, they are the most likely incorrect assumptions people will
start from.
 
G

greg

Steven said:
Consequently people who know these other
languages come along and ask "So is Python call by value or call by
reference?".

And if you don't know *exactly* what *they* understand by those
terms, you can't answer that directly without running the
risk of confusing them in some way. So instead, you just
tell them how it works, and leave them to decide for themselves
what name they want to give it.
 
A

Aaron Brady

Call by value is traditionally defined in at least some languages as
meaning that a copy of the value of the parameter is passed to the
function. Those languages include C and Pascal, and possibly Basic. I'd
estimate that 80% of programmers over the last 40 years have had their
understanding of "call by whatever" shaped by those three languages.

I see. Python promises not to make a copy unless you explicitly tell
it to. Therefore, Python is not call-by-value. Did I miss a step?

Formally:

M: Call-by-value makes a copy.
m: Python does not make a copy.
C: Python is not call-by-value.

Har har!
 
A

Aaron Brady

Maybe I missed this part.  What does the phrase, "value of variable x"
mean in Python?  Is it the same as what it means in C, Pascal, etc.?
In other words,
x= [ 2, 3, 4 ]
'0x%x'%id( x ) '0xb39dd0'

What is the value of 'x'?
a) [ 2, 3, 4 ]
b) An object with contents [ 2, 3, 4 ]
c) 0xb39dd0
d) None of the above.

Solution a) is just shorthand for b), because there are (or at least
could be) many such objects [2, 3, 4]. So I'd accept either a) or b) as
reasonable answers.

snip

I'm actually going to take issue with this... not to beat a dead
horse. (a) and (b) are distinct, at least potentially, and Steven did
not supply the burden of proof necessary for answering more than one.

More specifically, I want a definition of what it means "to copy an
object onto the stack". If one wanted to say, "copy a reference to it
onto the stack", would one say it, necessarily and always? In other
words, can one infer from a fact that one didn't say the latter, that
one didn't mean it?

People just express themselves and don't always speak with
mathematical precision. But, doing so, an object is not the same as a
reference to it, and all Python does is pass and copy references.

In fact, observing that the equals sign is not a mutating operation,
I'd even hold that Python calls by reference.
 
S

Steven D'Aprano

But, doing so, an object is not the same as a reference to it, and all
Python does is pass and copy references.

No, that's what at least one particular implementation of Python does.
That's not what Python does. The Python VM doesn't have any concept of
"values" or "references" or "values which are actually references in
disguise". The Python VM knows about *names in namespaces* and *objects*.
 
A

Aaron Brady

No, that's what at least one particular implementation of Python does.
That's not what Python does. The Python VM doesn't have any concept of
"values" or "references" or "values which are actually references in
disguise". The Python VM knows about *names in namespaces* and *objects*.

I think we can conclude that Python passes by reference, since a
function can modify objects that were passed in to it.
 
J

Joe Strout

I think we can conclude that Python passes by reference, since a
function can modify objects that were passed in to it.

Then please write the Python equivalent of the "Swap" methods shown at
>, for that matter).

And no fair wrapping the two parameters up in an object or using tuple
packing/unpacking -- the point is to demonstrate that you can change
the two parameters themselves, not some object that contains them or
return them a different order.

And by the way, if mutating an object a parameter refers to qualifies
as pass by reference, then Java, VB.NET/REALbasic (in ByVal mode), and
C/C++ all pass by reference too. That'll be quite a surprise to their
compiler authors! (I should know, as I'm one of them.)

Best,
- Joe
 
H

Hendrik van Rooyen

Aaron Brady said:
I think we can conclude that Python passes by reference, since a
function can modify objects that were passed in to it.

Sort of - if the modification is by "side effect" - so you
can append to a list, for instance.

However, if you use the passed param name on the left
of an assignment statement, you get a new local object.
I think it is this that lies at the root of the confusion.

- Hendrik
 
A

Aaron Brady

Then please write the Python equivalent of the "Swap" methods shown at  
<http://www.strout.net/info/coding/valref/> (or at <http://javadude.com/articles/passbyvalue.htm
 >, for that matter).

And no fair wrapping the two parameters up in an object or using tuple  
packing/unpacking -- the point is to demonstrate that you can change  
the two parameters themselves, not some object that contains them or  
return them a different order.

And by the way, if mutating an object a parameter refers to qualifies  
as pass by reference, then Java, VB.NET/REALbasic (in ByVal mode), and  
C/C++ all pass by reference too.  That'll be quite a surprise to their  
compiler authors!  (I should know, as I'm one of them.)

Best,
- Joe

Python can do the swap operation on mutable types, for example.

By-Value and By-Reference are not the only passing methods. True or
False?
 
J

Joe Strout

Python can do the swap operation on mutable types, for example.

That's in the "no fair" category. C can do a swap operation on
mutable types, too, though it also has only pass-by-value. Same for
Java, or for REALbasic or VB.NET using "ByVal" mode. The fact that
you can mutate mutable types has absolutely nothing to do with whether
the parameter was passed by reference or value. If was by reference,
you can change it (the parameter itself, not something the parameter
may refer to). If it's by value, you can't.

In Python, you can't. That's because parameters are passed by value.
By-Value and By-Reference are not the only passing methods. True or
False?

True, but the others are rarely used and don't apply to any of the
languages we've been discussing.

Best,
- Joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,685
Members
48,796
Latest member
Greg L.

Latest Threads

Top