Finding the instance reference of an object

S

Steven D'Aprano

The *formal* argument *is* a name, and that's what the phrase "changes
to the arguments within the called procedure" is talking about.

If you equate "arguments within the called procedure" to the *name* of
the arguments, then changing the arguments would mean changing the NAME,
not the object bound to the name. That is, something like this:

def foo(x):
y = x
del x

except as a single operation. I'm sure that's not what you intended to
say, but that's what you have said. Except for del and rebinding, Python
level code does not allow you to do anything to *names*, only to objects.
But I'm sure you know this, which makes your claim all the more confused.

More to the point, it sees the *name x* rather than the name y, and
rebinding the name x doesn't change the binding of name y. Therefore,
the name y has been passed by value, not by reference.

The term for what you have just said is "non sequitor", Latin for "it
does not follow". The _name_ y is not passed AT ALL. If there is a value
that is passed, it is the object bound to y, and not any name at all.

If you equate "value" with "object", as you suggested some posts ago,
then it could be argued that Python is call-by-value (for value=object)
but because "call by value" has connotations and implications that do not
apply to Python, we prefer to avoid the misleading and confusing term
c-b-v in preference to Barbara Liskov's term "call by sharing" or "call
by object".

At least some sections of the Java community seem to prefer a misleading
and confusing use of the word "value" over clarity and simplicity, but I
for one do not agree with them.


[1] You can pass a string representing the name to a function, which
can then use some combination of setattr, globals(), exec etc to work
with the name represented by that string.

This would be the Python equivalent of the strategy used in C to emulate
call-by-reference -- and it's needed for the same reason, i.e. the
language itself only provides call-by-value. So you pass a value that
you can manually dereference to get the same effect.

In the general case, you can't emulate call-by-reference by passing a
name, because you don't know what the name of an object is. Obviously I
can hard-code some names:

def swap(x, y):
# arguments x and y are actually pointless
g = globals()
g['x'], g['y'] = g['y'], g['x']


but you can't emulate c-b-r's ability to swap arbitrary names determined
by the compiler. The reason is that when you call a function with an
argument, the function sees only the object, and the object does not know
what name(s) is bound to it.


You could do this:

def swap(x_name, y_name):
g = globals()
g[x_name], g[y_name] = g[y_name], g[x_name]

which gives you something a little closer to c-b-r, but it still isn't
the same thing. Some major differences:

- you can't affect values unless they are bound to a name, that is no
swapping of anonymous values, e.g. swap(a[4], a[8]) could not work;

- within a nested scope, you can't affect anything unless it is in the
global scope;

- you need to know the name to apply at runtime, there is no way to
programmatically discover it.

The third point is the most telling. Consider the Pascal procedure:

procedure swap(var x, var y: integer):
var tmp: integer;
begin
tmp := x;
x := y;
y := tmp;
end;


Given two integer variables a and b, you call the procedure swap(a, b),
and the compiler can determine what memory addresses are used. If Pascal
was like Python, you would have to determine the addresses yourself:

a := 1;
b := 2;
swap(12693024, 190342874);

after which a would equal 2 and b would equal 1. Obviously Pascal is not
like that, but Python is (using names instead of memory locations). This
proves that Python names are nothing like Pascal call-by-reference
arguments. Passing a name is *not* Python's way to emulate call-by-
reference.
 
S

Steve Holden

greg said:
That's more like referring to the name 'Napoleon' in
two different namespaces. The original binding still
exists, you're just switching contexts.


I don't believe it's possible to build any complete and
correct model of Python behaviour without including some
concept equivalent to a reference.

You can talk about names written on PostIt notes and
such like, but that only gets you a short way. It doesn't
easily handle names in different namespaces, or references
that exist without simple names, e.g. list and tuple
items. Trying to repair these deficiencies only leads to
increasingly bizarre and contrived mental pictures.
+1

On the other hand, if you explicitly include the concept
of a reference from the beginning, everything is quite
clear and consistent.
Yes. References do explain things very well, since the model is in exact
agreement with the reality of the implementation.
In other words, the model should be as simple as possible
but no simpler. Leaving out references makes it too
simple.

Another point I'd like to make is that there is nothing
inherently low-level about the concept of a reference.
It doesn't have to be implemented as a memory address or
any other particular machine-level thing. It's possible to
talk about Python object references in a completely
implementation-independent way.
Indeed one might make use of some object store, and references would
still be useful even if they weren't memory addresses.
Also, just because you don't explicitly refer to them and
manipulate them at the language level doesn't mean they
don't exist. To think otherwise is like thinking that air
doesn't exist just because you can't see it. There are
plenty of experiments which clearly indicate its existence.
Likewise, there are plenty of experiments that you can
perform with any Python interpreter that reveal the
existence of references, or something equivalent to them.
Good stuff. I have come to the conclusion that this thread is mostly
best left alone, since the remaining participants appear to have agreed
on Python's semantics and now continue to argue about what name should
be used to describe them.

regards
Steve
 
G

greg

Steven said:
If you equate "arguments within the called procedure" to the *name* of
the arguments, then changing the arguments would mean changing the NAME

If "changing the name" means "rebinding the name",
then I agree -- that's exactly the point I was trying to
make.
If you equate "value" with "object", as you suggested some posts ago,

*I* didn't suggest that, someone else did. I was just
pointing out that you can use the word that way if you
want, as long as you're consistent about it. And being
consistent means using it in the same way when talking
about assignment and about by-value parameter passing.
If you insist that one of these implies copying the
"value" but the other doesn't, then you're being
inconsistent.
At least some sections of the Java community seem to prefer a misleading
and confusing use of the word "value" over clarity and simplicity, but I
for one do not agree with them.

I don't see anything inherently confusing or misleading
about it. Confusion only arises when some people jump up
and say that it's wrong to use the terms that way, because
it might cause confusion...
In the general case, you can't emulate call-by-reference by passing a
name, because you don't know what the name of an object is.

That's true, you need to communicate the namespace as
well, either implicitly or explicitly. So a
(namespace, name) pair, or a (sequence, index) pair
in the case of a sequence item, would be the equivalent
of a "reference" in the sense meant by "call by reference".
 
G

greg

Here is the definition of call-by-value from the
"Revised Report on the Algorithmic Language Algol 60"
<http://www.masswerk.at/algol60/report.htm>:

4.7.3.1. Value assignment (call by value). All formal parameters quoted in the
value part of the procedure declaration heading are assigned the values (cf.
section 2.8. Values and types) of the corresponding actual parameters, these
assignments being considers as being performed explicitly before entering the
procedure body. The effect is as though an additional block embracing the
procedure body were created in which these assignments were made to variables
local to this fictitious block with types as given in the corresponding
specifications (cf. section 5.4.5).

There you have it -- call by value is offially defined in
terms of assignment. There is no mention in there of copying.

So it's perfectly correct to use it in relation to Python.
 
A

Aahz

Here is the definition of call-by-value from the
"Revised Report on the Algorithmic Language Algol 60"
<http://www.masswerk.at/algol60/report.htm>:

4.7.3.1. Value assignment (call by value). All formal parameters quoted in the
value part of the procedure declaration heading are assigned the values (cf.
section 2.8. Values and types) of the corresponding actual parameters, these
assignments being considers as being performed explicitly before entering the
procedure body. The effect is as though an additional block embracing the
procedure body were created in which these assignments were made to variables
local to this fictitious block with types as given in the corresponding
specifications (cf. section 5.4.5).

There you have it -- call by value is offially defined in
terms of assignment. There is no mention in there of copying.

So it's perfectly correct to use it in relation to Python.

Except, of course, for the fact that it is generally misleading.
 
S

Steven D'Aprano

Here is the definition of call-by-value from the "Revised Report on the
Algorithmic Language Algol 60"
<http://www.masswerk.at/algol60/report.htm>:


Why should anyone take the "Revised Report on the Algorithmic Language
Algol 60" as the "official" (only?) definition of call-by-value for all
languages everywhere?

Particularly since in practice, people's *understanding* of such terms
have more to do with common practice than formal definitions. You're
welcome to tell people that tomatoes are actually berries from the Deadly
Nightshade family of plants, rather than vegetables, but if you do so you
better follow it up with further explanations.


4.7.3.1. Value assignment (call by value). All formal parameters quoted
in the value part of the procedure declaration heading are assigned the
values (cf. section 2.8. Values and types) of the corresponding actual
parameters, these assignments being considers as being performed
explicitly before entering the procedure body. The effect is as though
an additional block embracing the procedure body were created in which
these assignments were made to variables local to this fictitious block
with types as given in the corresponding specifications (cf. section
5.4.5).

I notice that you deleted the last sentence of the definition. I quote:

"As a consequence, variables called by value are to be considered as
nonlocal to the body of the procedure, but local to the fictitious block
(cf. section 5.4.3)."

And what's the fictitious block? As I understand it, their intention is
to say that calling a procedure foo(x) with an actual argument y should
be considered the same as:

# start a new block (a new scope, in Python terminology)
x = y # behave as if we explicitly assigned y to x
foo(x) # enter the body of foo with argument x local to the new block


What are the consequences of such assignment? Unfortunately, assignment
isn't unambiguously defined:


"4.2.3. Semantics. Assignment statements serve for assigning the value of
an expression to one or several variables or procedure identifiers.
Assignment to a procedure identifier may only occur within the body of a
procedure defining the value of a function designator (cf. section
5.4.4). The process will in the general case be understood to take place
in three steps as follows:
4.2.3.1. Any subscript expression occurring in the left part variables
are evaluated in sequence from left to right.
4.2.3.2. The expression of the statement is evaluated.
4.2.3.3. The value of the expression is assigned to all the left part
variables, with any subscript expressions having values as evaluated in
step 4.2.3.1."


In other words, assignment takes three steps:

(1) evaluate the subscript expressions on the left part (presumably of
the statement);

(2) evaluate the expression of the statement (presumably the right hand
side, but the document doesn't make that clear);

(3) assign the value of the expression.

Got that? Assignment means the value is assigned. Glad that's all clear
then.

So given an assignment of x = y in Algol, it isn't clear from this
document whether x and y refer to the same value, or if they merely have
the same value by equality. That second case would imply copying. To put
it in Python terms, following x = y we know that x == y is true but we
don't know whether id(x) == id(y).


Can we at least determine what variables and values are? Well, almost...

"3.1.3. Semantics. A variable is a designation given to a single value."

Okay, a variable is a designation (a name if you prefer) for a value. So
what's a value?


"2.8. Values and types

A value is an ordered set of numbers (special case: a single number), an
ordered set of logical values (special case: a single logical value), or
a label.
Certain of the syntactic units are said to possess values. These values
will in general change during the execution of the program The values of
expressions and their constituents are defined in section 3. The value of
an array identifier is the ordered set of values of the corresponding
array of subscripted variables (cf. section 3.1.4.1)."


Now we're getting somewhere! Values are sets of numbers or sets of true/
false logical elements. Hmmm... apparently strings aren't values in
Algol. Oh well.

But one thing is clear: values aren't references. Given the assignment
x=1, the value of x is not "a reference to 1" but 1 itself. So the one
thing we can unambiguously say is that Algol's assignment model is not
the same as Python's assignment model.
 
S

Steven D'Aprano

But one thing is clear: values aren't references. Given the assignment
x=1, the value of x is not "a reference to 1" but 1 itself. So the one
thing we can unambiguously say is that Algol's assignment model is not
the same as Python's assignment model.

Sorry, this is very misleading.

What I meant to say is that if you are one of those people who insist
that values in Python are references, then Algol's assignment model is
not that same as what you understand Python assignment to be.

I am very happy to say that x=1 implies that the value of x is the object
1 itself, in fact I would insist on such a definition of value.

If you insist that Python is call by value, the only way that can work is
by defining values to be references, which is nothing like Algol.
 
A

Arnaud Delobelle

Steven D'Aprano said:
I am very happy to say that x=1 implies that the value of x is the object
1 itself, in fact I would insist on such a definition of value.

If you insist that Python is call by value, the only way that can work is
by defining values to be references

That's a neat and concise way of summarising this whole thread.
 
F

Fredrik Lundh

Aahz said:
Except, of course, for the fact that it is generally misleading.

It's not only misleading, it's also a seriously flawed reading of the
original text - the Algol 60 report explicitly talks about assignment of
*values*.

I'm not aware of any language where a reference to an object, rather
than the *contents* of the object, is seen as the object's actual value.
It's definitely not true for Python, at least.

</F>
 
G

greg

Steven said:
Why should anyone take the "Revised Report on the Algorithmic Language
Algol 60" as the "official" (only?) definition of call-by-value for all
languages everywhere?

Since the term was more or less invented by the people
who designed Algol, I thought it would be a good idea to
find out, from as close to the source as possible, what
*they* intended it to mean.
Particularly since in practice, people's *understanding* of such terms
have more to do with common practice than formal definitions.

If "common practice" includes languages such as Java,
VB and RealBasic, then it accords with the original
definition, as far as I can see.
I notice that you deleted the last sentence of the definition. I quote:

"As a consequence, variables called by value are to be considered as
nonlocal to the body of the procedure, but local to the fictitious block
(cf. section 5.4.3)."

I didn't include that because it's not really relevant --
it's an artifact of the way they describe the effect of a
procedure call by conceptually substituting the call with
the text of the called procedure. You can equally well
think of the parameters as being in the same scope as the
rest of the procedure's locals.
What are the consequences of such assignment?

It doesn't matter what assignment means in Algol, because
we're talking about Python. We already agree on what assignment
means in Python -- or at least I hope we do!
 
G

greg

Steven said:
If you insist that Python is call by value, the only way that can work is
by defining values to be references, which is nothing like Algol.

No, that's not the only way. You can also make it work
by accepting the original definition of call-by-value
at face value -- i.e. as equivalent to assignment,
without any implication of copying beyond what
assignment itself implies.
 
G

greg

Fredrik said:
It's not only misleading, it's also a seriously flawed reading of the
original text - the Algol 60 report explicitly talks about assignment of
*values*.

Do you agree that an expression in Python has a value?

Do you agree that it makes sense to talk about assigning
that value to something?

If so, what is there to stop us from applying the Algol
definition to Python?
 
S

Steve Holden

greg said:
Do you agree that an expression in Python has a value?
Most expressions have values. The ones whose evaluations don't raise
exceptions.
Do you agree that it makes sense to talk about assigning
that value to something?
No. Why do you think that we are (mostly) careful to talk about binding
names and values instead?
If so, what is there to stop us from applying the Algol
definition to Python?
Apparently nothing. But then various participants in this thread have
demonstrated an apparently infinite capacity to split hairs with the
presumed intention of proving themselves right and others wrong. By now
you are arguing at the level of whether turquoise can be called blue.
Frankly, my dear, I don't give a damn.

Now, can we get on to something substantive like how many angels can
dance on the head of a pin?

regards
Steve
 
F

Francesco Guerrieri

Now, can we get on to something substantive like how many angels can
dance on the head of a pin?

Oh, come on, that's too easy! 42.
I thought that by now everybody knew that.

Francesco
 
F

Fredrik Lundh

greg said:
Do you agree that an expression in Python has a value?
>
Do you agree that it makes sense to talk about assigning
that value to something?

Python's definition of the word "value" can be found in the language
reference:

http://docs.python.org/reference/datamodel.html#objects-values-and-types

Using that definition, a Python expression yields an object, not an
object value.

For comparison, here's Algol's definition of the word "value":

"A value is an ordered set of numbers (special case: a single number),
an ordered set of logical values (special case: a single logical value),
or a label."

It should be obvious to anyone that Python is not Algol.
> If so, what is there to stop us from applying the Algol
> definition to Python?

The fact that we're talking about Python. Python is not Algol.

</F>
 
A

Aahz

I stopped paying much attention to this thread a while ago, but
you've got to admire the persistence of somebody who soldiers
on even though Aahz, Fredrik Lund, and Steve Holden are all on
the other side of the argument...

QOTW! ;-)
 
G

George Sakkis

Python's definition of the word "value" can be found in the language
reference:

http://docs.python.org/reference/datamodel.html#objects-values-and-types

Quoting the relevant part:

"The value of some objects can change. Objects whose value can change
are said to be mutable; objects whose value is unchangeable once they
are created are called immutable."

Strictly speaking that's not a definition; it doesn't say what a value
is, only how it relates to objects. But regardless, according to this,
a Python value is what the rest of the world usually calls "state",
while a value in a non-Python context is usually a synonym of
"object" (in the general sense, e.g. for Java including both
primitives and object references), i.e. there's the following
approximate mapping in terminology:

Python jargon Non-python jargon
===========================
object value (primitive or composite)
value state (set of an object's attribute bindings)

Thus both call-by-value and call-by-object can be correct
descriptions, depending on who you ask.

George
 
C

Craig Allen

arguably even older than that to Lisp.

Firstly, thanks to those that have responded to my part in this
debate, I have found it very informative and interesting as I have the
entire thread. However, with regard to comments that I led myself
astray, I want to reiterate the one thing I find determinably
important in this... I did not go astray because I did not fret what
the words meant and try to draw anything from that. I learned exactly
what would happen when I passed arguments different ways, and I
learned that well and accurately. Then I mused what to call it all. At
no time was I astray because I think to really be astray would be to
have a misunderstanding on what happens, not on what we call what
happens.

but I will concede that trying to use call-by-name is not a viable
idea as it's yet another term that is already taken. I did not think
too hard what the distinction is, and as far as I know it's as good a
candidate for what we call it as anything else, but I certainly don't
want to fight for the term. Whatever we call the passing semantics
and methods in Python... it will not change what I understand about
what happens with certain kinds of calls vs others.

cheers.
 
G

greg

Steve said:
No. Why do you think that we are (mostly) careful to talk about binding
names and values instead?

That's an odd position to take, considering that the
Python docs use the word "assignment" all over the
place, and the language even has a statement known
as an "assignment statement".

The Python Language Reference has this to say about
assignment:

The following constructs bind names: formal parameters to functions, import
statements, class and function definitions (these bind the class or function
name in the defining block), and targets that are identifiers if occurring in
an assignment...
[http://docs.python.org/reference/executionmodel.html]

What this suggests to me is that the reason the
Language Ref talks about binding is not because there's
anything wrong with the word assignment, but because
binding is a more general term. Assignment is one way
to perform binding, but there are other things that
perform binding as well.
But then various participants in this thread have
demonstrated an apparently infinite capacity to split hairs with the
presumed intention of proving themselves right and others wrong.

For my part, I'm not trying to "prove myself right",
I'm trying to be helpful by clearing up what seems to
me to be a misunderstanding about what the term
call-by-value implies. But it appears that some people
stubbornly refuse to have their misunderstandings
cleared up. :)

That's how it looks from my end, anyway. No doubt from
the other end it looks like I'm the one being stubborn.
That's why I've been trying to inject some objectivity
by doing some research and finding authoritative
references to back up what I'm saying.

I'm learning things from all this, too. For example,
until recently I couldn't be sure I wasn't the only
person in the world who had thought of the idea of
defining call-by-value in terms of assignment rather
than copying. Turns out I'm not -- Backus et al, no
less, had exactly the same idea. And it seems they're
not the only ones, either -- more on that later.
 
G

greg

Grant said:
I stopped paying much attention to this thread a while ago, but
you've got to admire the persistence of somebody who soldiers
on even though Aahz, Fredrik Lund, and Steve Holden are all on
the other side of the argument...

Those people clearly know a great deal about Python,
and I respect them for that. However, that doesn't
necessarily make them authorities on programming
language terminology.

If you're going to indulge in argument by authority,
you need to pick authorities that can be considered,
er, authoritative in the field concerned...
 

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

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,185
Latest member
GluceaReviews

Latest Threads

Top