Finding the instance reference of an object

Fuzzyman fuzzyman at gmail.com
Wed Oct 29 18:52:33 EDT 2008


On Oct 28, 3:59 pm, Joe Strout <j... at strout.net> wrote:
> On Oct 27, 2008, at 11:28 PM, Gabriel Genellina wrote:
>
>
>
> > En Tue, 28 Oct 2008 00:58:10 -0200, greg  
> > <g... at cosc.canterbury.ac.nz> escribió:
>
> >> Let's look at the definitions of the terms:
>
> >> (1) Call by value: The actual parameter is an expression. It is
> >>    evaluated and the result is assigned to the formal parameter.
> >>    Subsequent assignments to the formal parameter do not affect
> >>    the actual parameter.
>
> >> (2) Call by reference: The actual parameter is an lvalue. The
> >>    formal parameter becomes an alias for the actual parameter,
> >>    so that assigning to the formal parameter has the same
> >>    effect as assigning to the actual parameter.
>
> >> Seems to me that (1) describes exactly how parameter passing
> >> works in Python. So why insist that it's *not* call by value?
>
> Greg is right on the money here.  It really is as simple as that.
>
> > Those definitions are only applicable to unstructured, primitive  
> > types, where the only relevant operations are "get value" and  
> > "assign value".
>
> Nonsense.  They apply to any type.  See here for an introduction to  
> the topic in VB.NET:
>
>    http://www.homeandlearn.co.uk/net/nets9p4.html
>
> The example shown uses an Integer, but guess what -- you can pass ANY  
> type either ByRef or ByVal, including object references (which are, of  
> course, quite common in VB.NET).  The default is ByVal, which means  
> that (as in Python) the actual parameter is an expression, and no  
> assignments to it can affect the actual parameter.  It DOES NOT MATTER  
> that both the formal parameter and the actual parameter may refer to  
> the same object, and if that object is mutable, you can mutate that  
> object.
>

You're pretty straightforwardly wrong. In Python the 'value' of a
variable is not the reference itself. If that sentence has any meaning
for Python then the value is the object itself.

.NET does draw a distinction between 'value types' and reference types
- where using reference types are called by reference (the reference
is passed) and value types are called by value (the value itself is
copied).

Value types (all numeric types, structs, enumerations etc) actually
live on the stack, whereas reference types (strings, classes etc) live
in the heap and have a
pointer on the stack.

It is complicated by the fact that .NET perpetuates the myth that the
primitives (the value types) inherit from System.Object (a reference
type). The runtime does auto-boxing for you where this matters.

This means that when you pass a value type into a method the value
*is* copied. Structs can be arbitrarily big, so this can be a
performance problem. It is often a performance win for working with
the numeric types as you remove a level of indirection.

It isn't without problems though - and some of these can be seen in
IronPython.

System.Drawing.Point is a struct, but it is effectively a mutable
value type. However, when you access it you are often accessing a copy
- and if you attempt to mutate it then your changes will be lost.

The following code illustrates the problem:

>>> r = Rectangle(0, 1002 20, 40)
>>> r.Location.X
0
>>> r.Location.X = 20
>>> r.Location.X

0

Because r.Location returns a value type (a Point), the update to it is
'lost'.

By this definition Python objects (all of them) are clearly reference
ypes and not value types.

In .NET you can specify that a parameter to a method takes a reference
('out' in C# or ByRef in VB.NET). If you pass in a value type as a
reference parameter then the .NET runtime will do boxing / unboxing
for you.

This means that we can write code like the following C#:

int x = 3;
SomeMethod(out x);

The value of x can be changed by 'SomeMethod' and can have a different
value - something that can't happen in Python.

In a 'way' immutable Python types behave a bit like .NET value types,
and mutable types like reference types. As you can see, this analogy
breaks down.

Michael Foord
--
http://www.ironpythoninaction.com/



> But ByRef is another option, and if you pass an object reference  
> ByRef, then the formal parameter is an alias for the actual parameter,  
> and assignments to it change the actual parameter.  Python doesn't  
> have this feature (nor much need for it, given its other features,  
> like tuple packing/unpacking).  So, parameter passing in ByRef is  
> clearly exactly the same as the default "ByVal" parameter passing in  
> VB.NET... as well as Java, RB, C++ (when you remember that an object  
> reference in modern languages is like a pointer in C++), and every  
> other OOP language I've looked into.
>
> Some of those languages, like Python, don't have different modes, and  
> so the language designers had no call to give their one mode a name.  
> So let's look at those that did have such a need, like VB.NET and  
> REALbasic.  What's the default mode called?  Why, it's "ByVal".  Even  
> when that value is an object reference.  This is short for "by value"  
> -- it's not short for "by sharing" or "by object" or any other such  
> silliness.  No such terms are needed.
>
> There are only the two cases, which Greg quite succinctly and  
> accurately described above.  One is by value, the other is by  
> reference.  Python quite clearly uses by value.  Parameters are  
> expressions that are evaluated, and the resulting value copied into  
> the formal parameter, pure and simple.  The continued attempts to  
> obfuscate this is pointless and wrong.
>
> Best,
> - Joe




More information about the Python-list mailing list