# Finding the instance reference of an object

Steve Holden steve at holdenweb.com
Fri Oct 17 22:36:24 CEST 2008

```Joe Strout wrote:
> On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
[much blether]
>>> Side question, for my own education: *does* Python have a "ByRef"
>>> parameter mode?
>>>
>>     As far as I'm concerned -- everything is "by ref" in Python...
>
> No, a "by ref" parameter would mean that this:
>
> def foo(ByRef x):
>  x = x + [42]
>
> a = [1,2,3]
> foo(a)
>
> ...would result in a = [1,2,3,42].  You would only be able to pass a
> simple variable (not an expression or literal) to foo, and the 'x'
> inside foo would not be a local variable, but an alias of whatever
> variable was passed in.  Thus any assignments to it would affect the
> original variable that was passed in.
>
In [8]: def foo(x):
...:     x += [42]
...:

In [9]: a = [1, 2, 3]

In [10]: foo(a)

In [11]: a
Out[11]: [1, 2, 3, 42]

In [12]: def ffoo(x):
....:     x.append(43)
....:

In [13]: ffoo(a)

In [14]: a
Out[14]: [1, 2, 3, 42, 43]

In [15]: def fffoo(a):
....:     a = a + [42]
....:

In [16]: fffoo(a)

In [17]: a
Out[17]: [1, 2, 3, 42, 43]

So, is it call by reference or not? Does that depend on the
implementation of specific operators?

You problem seems to be that you ar still stuck with the notion of a
name as a reference to a specific area of memory. Which it's not,
excepting only if you want to consider the area of memory that holds a
reference to some value.

In the case of lists,

a = a + [something]

rebinds a, while

a += [something]

doesn't. So where does that leave you?

> But if Python has any such feature, I'm not aware of it.  Certainly the
> default behavior is to pass everything (even object references) by
> value.  Assignments made to them don't affect anything else.
>
>>     Mutation of an object is never a bare LHS... It is either a method
>> call of the name
>>
>>     alist.append()
>>
>> or a drill-down going inside the object
>>
>>     alist[2] = something
>>     anobject.attribute = something
>
> Or, use of one of the compound operators like +=.  That's the only real
> "gotcha" in Python to somebody coming from another language; you might
> naively expect that x += y is the same as x = x+y, but in Python this is
> not generally the case; instead += is a mutation operator, like the
> examples you show above.
>
Be careful though:

In [18]: a = 42

In [19]: id(a)
Out[19]: 14237932

In [20]: a += 1

In [21]: id(a)
Out[21]: 14237920

In [22]: a = []

In [23]: id(a)
Out[23]: 2140206636

In [24]: a += [42]

In [25]: id(a)
Out[25]: 2140206636

In other words, the behavior of augmented operations depends on whether
the reference is to a mutable or an immutable value.

>>     But every language I've used (many: FORTRAN, C, C++, BASIC, VB,
>> Assembly, COBOL, Ada...) treats "variable" as "name of fixed location in
>> memory" and assignment to the variable means "replace the contents of
>> the location of memory associated with this name with the contents of
>> memory to which that name (may be anonymous in the case of an
>> expression) is associated by copying the contents from there to here"
>
> That's what Python does too.  It just so happens that the fixed location
> in memory contains an object reference.  No difference here between
> Python's object references VB.NET's object references, C++ pointers,
> Java object references, etc. etc.
>
>>     Python, OTOH, ALWAYS handles assignment as "change the memory
>> association of this name to be the same as that name".
>
It might be simpler to say "Change this name to be a reference to that
value", or "Change this name to be a reference to the [result of
evaluating the] expression on the RHS".

Or indeed, "Change the content of that container element to be a
reference to the [result of evaluating the] expression on the RHS"

> What does that mean, exactly?  It means: "replace the contents (i.e.
> object reference) of the memory location associated with this name with
> the contents (i.e. object reference)  of the memory to which that name
> is associated by copying the contents from there to here."
>
> It's the exact same thing.  (And exactly the same as in any other
> language.)
>
If you mean it's a reference assigment, of course it is. That's what he
was trying to say (I believe). But in C, for example,

int i;
i = 42;

actually stores the value 42 in the location associated with the name c.
Quite different from

int *i;
i = &42;

[Is that even valid C?] That's almost what Python does with

i = 42

>>> No, but if we define them in the standard way, and point out that
>>> Python variables behave exactly like variables in other languages,
>>>
>>     But they don't...
>
> They really, really do.
>
>>> But it's not at all surprising with lists and dicts and objects --
>>> every modern language passes around references to those, rather than
>>> the data themselves, because the data could be huge and is often
>>> changing size all the time.  Storing the values in a variable would
>>> just be silly.
>>>
>>     In most all of those languages, one has to explicitly differentiate
>> the the difference between a copy and a reference.
>
> Only if you're thinking of languages from 20 years ago or more.  Even in
> C++, while there is a different bit of kludgy syntax for object
> "references" (because they're mere pointers), it's the standard to use
> such pointers everywhere that objects are handled.  Java cleaned up that
> kludginess by replacing the pointers with proper references, as did
> VB.NET, REALbasic, probably Ruby, and of course Python.
>
>> And even that is not
>> assured... As I recall, nothing in the Ada language reference forbids
>> implementing an "in out" procedure parameter from being implemented via
>> copy-in/copy-out semantics rather than via reference.
>
> Hah, well probably so.  Ada even predates me, and I'm not all that young
> anymore!
>
>>> Hmm... I bet you're over 30.  :)  So am I, for that matter, so I can
>>> remember when people had to learn "pointers" and found it difficult.
>>
>>     Bah... The roots of I/O in Pascal required pointer dereferencing.
>
> Hey, I remember Pascal... that was the language used on the Apple IIGS,
> back when I was in junior high.  I also remember spending \$800 for a
> 40MB hard drive for it.  Ah, those were the days!
>
40 Mb! You were lucky! Etc., etc., [drools into beard.]

>>> So, if the semantics are all the same, I think it's helpful to use the
>>> standard terminology.
>>>
>>     But, it seems, you are the only one arguing that "the semantics are
>> all the same"... Doesn't that suggest that they aren't the same?
>
> No, it suggests to me that there's a lot of confusion in the Python
> community.  :)  It appears as though people either (a) really want to
> think that Python's object handling is special and unique for emotional
> reasons, or (b) are comparing it to really ancient languages that didn't
> have any notion of objects and object references.  This has led to
> making up new terminology and spreading confusion.  I'm coming back to
> Python from almost a decade of working with other modern languages
> (including implementing the compiler for one of them), and I don't see
> any difference at all between Python's object handling and those.
>
Python's assignment semantics (as opposed to its "object handling, a
term for which I have no referent) are not the same as those of, say C.
I believe they are pretty much the same ass those of Icon, another
non-standard interpreted language.

There are close similarities between Python's names and C reference
variables, but the semantics are not exactly parallel.

People here don't describe Python as different just because they *want*
it to be different. Python acknowledges intellectual debts to many
languages, none of which is exactly like it.

regards
Steve
--
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/

```