Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > RE: anything like C++ references?

Reply
Thread Tools

RE: anything like C++ references?

 
 
Ian Bicking
Guest
Posts: n/a
 
      07-12-2003
On Sat, 2003-07-12 at 17:45, Brian Quinlan wrote:
> > void change(int& i)
> > {
> > i++;
> > }

>
> The idiomatic way to write this code in python would be:
>
> def change(val):
> return val + 1


To be more specific, you would achieve the same effect with:

def change(val):
return val + 1
i = change(i)

As opposed to the C++ where you'd do:

change(i) // no assignment needed


There is no direct Python equivalent to the C++ function, for all sorts
of reasons (most of them very deliberate).

Is there someplace in particular to reference people who need to learn
about what Python variables are (that they are bindings, etc)? This
question comes up in many forms all the time, particularly from people
with a C background. Or rather, there are many questions all of which
are answered by that explanation (so we can't expect people to stop
asking, but maybe we can make the answers easier and clearer). Or maybe
a general Python-for-C-programmers tutorial...

Ian



 
Reply With Quote
 
 
 
 
Erik Max Francis
Guest
Posts: n/a
 
      07-13-2003
Tom Plunket wrote:

> IMHO the variable binding discussion doesn't answer the question,
> it just provokes more questions.


But the answer to those questions is usually something ending with,
"Look, Python just doesn't handle variables the same way C++ does."

--
Erik Max Francis && http://www.velocityreviews.com/forums/(E-Mail Removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \ It seems like Karma's making his rounds
\__/ Kina
 
Reply With Quote
 
 
 
 
Stephen Horne
Guest
Posts: n/a
 
      07-13-2003
On Sun, 13 Jul 2003 00:55:22 -0700, Erik Max Francis <(E-Mail Removed)>
wrote:

>Tom Plunket wrote:
>
>> IMHO the variable binding discussion doesn't answer the question,
>> it just provokes more questions.

>
>But the answer to those questions is usually something ending with,
>"Look, Python just doesn't handle variables the same way C++ does."


And my traditional answer to that is... "yes, and the way that Python
handles variables is definitely a wart."

One of the few things I hate about Python is that mutable objects are
implicitly shared using a reference system whereas immutable objects
are not. It is unnecessarily confusing and error prone.

A system where all objects are copied unless a reference type is
explicitly applied (and with an assignment operators recognising
references on the LHS by default and assigns to the object rather than
the reference, though with an extra one which overwrites the
reference) seems much more logical to me. It even seems 'Pythonic' to
me. But it is much closer to C++ references than current Python
system.

 
Reply With Quote
 
Roy Smith
Guest
Posts: n/a
 
      07-13-2003
Stephen Horne <(E-Mail Removed)> wrote:
> One of the few things I hate about Python is that mutable objects are
> implicitly shared using a reference system whereas immutable objects
> are not. It is unnecessarily confusing and error prone.


There's a bit of confusion in the above regarding mutability vs. call by
reference (they're orthogonal ideas), but I think I know what you were
trying to say.

In ancient versions of Fortran, even constants (i.e. immutables) were
pass by reference. You could write something like this (forgive me if
I've forgotten some of the syntax details):

subroutine x (i)
i = 42
end

subroutine main
x (5)
write (6, 100) 5
100 format (1i6)
end

and it would print 42. There was a single instance of the constant 5
for main, and it was passed by reference to x(), which in turn changed
its value to 42. I don't remember if Fortan 66 did this, or if that
only happened in even older versions. Talk about confusing and error
prone!

The Python version of that would be:

def mutateString (s):
s = "some other string"

s ("foo")
print "foo"

If strings were pass by reference, the above would print "some other
string". Unless, of course, you got away from the idea that multiple
instances of a string constant with the same value are really the same
object, in which case:

x = "foo"
x is "foo"

would print 0 instead of 1 like it does now.
 
Reply With Quote
 
Aahz
Guest
Posts: n/a
 
      07-13-2003
In article <(E-Mail Removed)>,
Stephen Horne <(E-Mail Removed)> wrote:
>
>One of the few things I hate about Python is that mutable objects are
>implicitly shared using a reference system whereas immutable objects
>are not.


Well, that's incorrect. *ALL* Python objects are implicitly shared with
bindings. The difference is whether updating the value referenced by a
target requires *re*binding the target or simply updating an object.
--
Aahz ((E-Mail Removed)) <*> http://www.pythoncraft.com/

"Not everything in life has a clue in front of it...." --JMS
 
Reply With Quote
 
Stephen Horne
Guest
Posts: n/a
 
      07-13-2003
On 13 Jul 2003 10:37:01 -0400, (E-Mail Removed) (Aahz) wrote:

>In article <(E-Mail Removed)>,
>Stephen Horne <(E-Mail Removed)> wrote:
>>
>>One of the few things I hate about Python is that mutable objects are
>>implicitly shared using a reference system whereas immutable objects
>>are not.

>
>Well, that's incorrect. *ALL* Python objects are implicitly shared with
>bindings. The difference is whether updating the value referenced by a
>target requires *re*binding the target or simply updating an object.


Fine - nit-pick.

All you have proven is that it is the distinction between types that
get re-bound and those that don't (rather than the use of references)
that is unnecessarily confusing and error prone.

The wart remains, even if my description was wrong. And even that is a
dubious claim.

A Python user is interested in how an object behaves - not how it is
internally implemented in the interpreter. Immutable objects don't
behave as references - the internal use of references for immutable
objects is basically a lazy copying optimisation and, apart from
performace and a couple of other technicalities (e.g. the 'is'
operator), has no relevance. Certainly it has no relevance to the
point I was making.

 
Reply With Quote
 
Stephen Horne
Guest
Posts: n/a
 
      07-13-2003
On 13 Jul 2003 12:19:08 -0400, (E-Mail Removed) (Aahz) wrote:

>Whether one can mutate a specific object is simply an
>attribute of that object, rather than requiring a different syntax.
>Trying to focus on the mutable/immutable distinction is what causes the
>mental blowup -- keep your eye on the objects and bindings and you're
>fine.


That's exactly it - you have to focus on whether an object is mutable
or immutable for that exact reason.

While I admit I'm not sure, I believe that in early versions of Python
immutable values literally were copied. Mutable types were made
mutable because of efficiency concerns about copying overheads that
would occur otherwise. If an object is large enough that it is
worthwhile modifying items within it in-place then it tends to be
worthwhile trying to avoid copying overheads, even though these two
aspects of 'mutability' are actually quite distinct in principle.

Actually, I'm convinced there are some flaws in Guidos own logic
*unless* this is the case. Take for instance this...

http://www.python.org/search/hyperma...1992/0292.html

"""
<A> They serve different purposes. Lists can get quite long, they are
generally built incrementally, and therefore have to be mutable.
Tuples on the other hand are generally short and created at once.


<Q> Then why can't tuples be mutable and serve both purposes?


<A> Imagine a graphics class that stores coordinates of graphical
objects as tuples. It may also store rectangles as a tuple of points,
etc. If tuples were mutable, the class would have to store copies of
all points and rectangles it receives, since otherwise a caller who
creates a point variable, passes its value to the graphics class, and
later changes the point for its own use (e.g., to create another
graphical object with slightly different coordinates) might violate
the internal consistency of the graphics class. Note that most
callers woouldn't modify the points, but the graphics class has no way
to tell, so it has to make the copies anyway. (And now imaging the
software is actually layered in such a way that coordinates are passed
down several levels deep...)
"""

So what?

As things are, the points could be stored using a list of tuples, with
each tuple representing a point. When you store a new point in the
list, you don't immediately make a copy (so if the supplier of the
point immediately discards it, no copying is needed at all except for
pointers) so it is efficient - yet you are still guarenteed that
external processing will not mutate the value you hold in your list.

Fine.

But that can be achieved equally well by applying a copy-on-write
system to *all* types, without a distinction between mutable and
immutable for this purpose.

Equally, you could use the same rationale for storing items which
Python classes as mutable instead of these point tuples. If you have
an object which stores class instances or dictionaries or lists for
you, you need to store copies as - just as Guido recognised for the
tuple case - your object doesn't know for sure what the caller is
going to do with those objects after passing them in as parameters.

This makes no sense to me *unless* there were other reasons for the
mutable/immutable distinction. If lists had copy-on-write semantics,
they could still be mutable (ie support in-place modification) yet
there would be no need to make early copies. Tuples would be redundant
as their only distinctive feature would be their lack of support for
in-place modifications. It only makes sense if the copy-on-write for
immutable values hadn't been implemented when the distinction was
created - if immutables did not use references, but were always copied
immediately on assignment - so that the referencing mechanism need
never worry about copy-on-write at all.


But it is worse than just being an arbitrary and pointless
distinction...

Back when PEP238 was being 'debated', a major argument in favor of the
change was that there is no legitimate case where a function would
need to either do 'true' division or integer division depending on the
argument type. The type of division needed depends on the purpose of
the function, and behaviour shouldn't change just because someone
passes an integer into a function that expects a real or visa versa.

Apply the same logic to mutable and immutable types.

Tell me one case where it is sensible for a function to behave such
that whether the caller sees a change in a variable it passed as its
argument should depend on the type.

Tell me one case where an object storing values should care about
callers mutating values it holds *only* for certain types.

I doubt you can.

This is an arbitrary distinction created for historic reasons that
have long since vanished (apart, of course, from backward
compatibility and psychological inertia), given that copy-on-write is
implemented for immutable objects anyway. And the fact that immutable
values do an excellent job of implementing the common semantics of
most imperitive languages (i.e. assignment sets the LHS to something
that can be treated as a distinct copy) whereas mutable types behave
in a fundamentally different way is quite simply a wart -
inconsistent, confusing and error-prone behaviour.

 
Reply With Quote
 
Donn Cave
Guest
Posts: n/a
 
      07-13-2003
Quoth Stephen Horne <(E-Mail Removed)>:
| On 13 Jul 2003 12:19:08 -0400, (E-Mail Removed) (Aahz) wrote:
|
|> Whether one can mutate a specific object is simply an
|> attribute of that object, rather than requiring a different syntax.
|> Trying to focus on the mutable/immutable distinction is what causes the
|> mental blowup -- keep your eye on the objects and bindings and you're
|> fine.
|
| That's exactly it - you have to focus on whether an object is mutable
| or immutable for that exact reason.
|
| While I admit I'm not sure, I believe that in early versions of Python
| immutable values literally were copied. Mutable types were made
| mutable because of efficiency concerns about copying overheads that
| would occur otherwise. If an object is large enough that it is
| worthwhile modifying items within it in-place then it tends to be
| worthwhile trying to avoid copying overheads, even though these two
| aspects of 'mutability' are actually quite distinct in principle.

Sure, mutable values literally are copied today. If you have a tuple
of time.localtime(x), for example, and you want that value but with
tm_mday incremented, then you must copy the tuple to do that (except
for tm_mday, for which you substitute your own value.) It is indeed
inefficient - OK for this purpose but not for large sequences, and
there we tend to prefer a mutable list.

That's the efficiency argument. Assigment never copied values, in
any version of Python that anyone cared about. We just don't want
big immutable arrays that have to be copied just to change a single
value. There isn't a tuple analogue for the dictionary because it
wouldn't be so generally useful (the recently implemented struct
tuple would have been nice to have earlier, though.)

He's quite right, the notion of mutability is a red herring. It
isn't that no one cares - the propagation of state changes in a
program is critical to the operation of the program, and to reasoning
about how the program will operate.

It's just that when you're trying to come to grips with how assignment
and argument passing works in Python, you don't want to have people
start explaining things in these terms (``see, this object is mutable
and that one isn't''), because you will understandably but incorrectly
apply that to assignment and argument passing. Mutability in Python
has no effect on assignment and argument passing, it is just an attribute
of the passed or assigned object.

Donn Cave, (E-Mail Removed)
 
Reply With Quote
 
Ian Bicking
Guest
Posts: n/a
 
      07-13-2003
On Sun, 2003-07-13 at 12:51, Stephen Horne wrote:
> On 13 Jul 2003 12:19:08 -0400, (E-Mail Removed) (Aahz) wrote:
>
> >Whether one can mutate a specific object is simply an
> >attribute of that object, rather than requiring a different syntax.
> >Trying to focus on the mutable/immutable distinction is what causes the
> >mental blowup -- keep your eye on the objects and bindings and you're
> >fine.

>
> That's exactly it - you have to focus on whether an object is mutable
> or immutable for that exact reason.


No you don't! Mutable and immutable objects act the same with respect
to assignment. However, because you cannot change a immutable object in
place, to get a different value you must rebind. You must *use* mutable
and immutable objects differently -- but that is not surprising, because
they are obviously very different objects! You have to use integers and
lists differently in part because one is mutable and the other isn't --
but mostly because one is a number and the other is a list. Different
objects are different!

Python is not novel in the way it deals with variables. Scheme and
Smalltalk, for instance, act exactly the same, as do many other
dynamically typed languages (though there are different opinions on
whether strings should be mutable -- but it's agreed there has to be
some immutable string-like type, e.g. symbol). The reason you are
getting this reaction is that anyone that comes from those backgrounds
thinks you are crazy, as does anyone who has embraced the Python model.
This isn't a funny little feature, this is the way all strong,
dynamically typed languages work.

> While I admit I'm not sure, I believe that in early versions of Python
> immutable values literally were copied. Mutable types were made
> mutable because of efficiency concerns about copying overheads that
> would occur otherwise. If an object is large enough that it is
> worthwhile modifying items within it in-place then it tends to be
> worthwhile trying to avoid copying overheads, even though these two
> aspects of 'mutability' are actually quite distinct in principle.


The problem you have is you are still thinking of variables as slots,
which is not correct. Variables in Python are bindings. Assignment
never copies anything, or creates anything except for changing the
variable to point to a different address location. *Every* Python
assignment (a=b) is like the C assignment (a=&b).

> Tell me one case where it is sensible for a function to behave such
> that whether the caller sees a change in a variable it passed as its
> argument should depend on the type.


Generally a function takes either immutable values (e.g., ints and
floats) or mutable values for a certain argument.

However, there is a class of operations which are generally operate in
an immutable manner, that is, create copies of the objects instead of
changing them in place. So even though lists are mutable, list
concatenation does not mutate, and in general adding two things (with +)
will not mutate either object. Immutable values, by design, do not have
the same methods and operations as the mutable counterparts (or at least
the mutating methods of those mutable objects). *That* would be a
design bug.

> Tell me one case where an object storing values should care about
> callers mutating values it holds *only* for certain types.


Objects don't *store* values, they *refer* to values. You are still
thinking like you're in C (or C++). This is why you are having a
problem.

Ian



 
Reply With Quote
 
Stephen Horne
Guest
Posts: n/a
 
      07-13-2003
On 13 Jul 2003 14:48:09 -0500, Ian Bicking <(E-Mail Removed)>
wrote:

>On Sun, 2003-07-13 at 12:51, Stephen Horne wrote:
>> On 13 Jul 2003 12:19:08 -0400, (E-Mail Removed) (Aahz) wrote:
>>
>> >Whether one can mutate a specific object is simply an
>> >attribute of that object, rather than requiring a different syntax.
>> >Trying to focus on the mutable/immutable distinction is what causes the
>> >mental blowup -- keep your eye on the objects and bindings and you're
>> >fine.

>>
>> That's exactly it - you have to focus on whether an object is mutable
>> or immutable for that exact reason.

>
>No you don't! Mutable and immutable objects act the same with respect
>to assignment. However, because you cannot change a immutable object in
>place, to get a different value you must rebind. You must *use* mutable
>and immutable objects differently -- but that is not surprising, because
>they are obviously very different objects! You have to use integers and
>lists differently in part because one is mutable and the other isn't --
>but mostly because one is a number and the other is a list. Different
>objects are different!
>
>Python is not novel in the way it deals with variables. Scheme and
>Smalltalk, for instance, act exactly the same, as do many other
>dynamically typed languages (though there are different opinions on
>whether strings should be mutable -- but it's agreed there has to be
>some immutable string-like type, e.g. symbol). The reason you are
>getting this reaction is that anyone that comes from those backgrounds
>thinks you are crazy, as does anyone who has embraced the Python model.
>This isn't a funny little feature, this is the way all strong,
>dynamically typed languages work.


In computer science, a variable is a named binding to a value.
Operations on that variable may rebind it to a different value, but
values don't change behind your back. A pointer is, in effect, a value
which indirectly refers to another (possibly anonymous) variable. A
pointer is something you specifically request, and by doing so you
allow that the 'variable' being indirectly referenced may be modified
by something else that has no direct access to your pointer value (via
your named variable or via copys or pointers-to your pointer held
elsewhere).

Python should respect that.

If you claim that it does, then the values to which we currently
associate the type name 'list', 'dictionary' and 'class instance' are
badly named. They should be called 'pointer to list', 'pointer to
dictionary' and 'pointer to class instance'. And if you want to call
those references and make the dereferencing implicit, fine. Equally,
if you want to implement variable binding using references and using
copy-on-write to implement lazy copying (which does not violate the
standard computer-theory semantics of the binding to values - only the
binding to the implementation of values ie memory locations) then
equally fine.

However, even if the names included the 'pointer to' prefix so that
they actually described the real behaviours of the values, this still
raises two important questions...

1. Why are the values of mutable objects always forced to be accessed
via a pointer (or reference or whatever)?

Note that I am referring to a computer science, semantic
pointer/reference/whatever - not to any pointers or references that
may be used in the implementation of the binding of variables to
values. The use, behind the scenes, of lazy copying as an optimisation
is irrelevant to the computer science principles.

2. Why is there no way to reference an immutable object via a
pointer, other than stuffing it into a mutable object designed for
some purpose other than simple pointer behaviour?

The truth is that this system is arbitrary, and that therefore this
excuse is invalid.

>The problem you have is you are still thinking of variables as slots,
>which is not correct. Variables in Python are bindings. Assignment
>never copies anything, or creates anything except for changing the
>variable to point to a different address location. *Every* Python
>assignment (a=b) is like the C assignment (a=&b).


The problem is that you are confusing implementation with semantics.
The meanings of 'variable', 'value', 'assignment' etc are defined by
computer science. Whether you arbitrarily change the meaning of
'assignment' or whether you arbitrarily change the meaning of
'variable', it amounts to the same thing.

>
>> Tell me one case where it is sensible for a function to behave such
>> that whether the caller sees a change in a variable it passed as its
>> argument should depend on the type.

>
>Generally a function takes either immutable values (e.g., ints and
>floats) or mutable values for a certain argument.
>
>However, there is a class of operations which are generally operate in
>an immutable manner, that is, create copies of the objects instead of
>changing them in place. So even though lists are mutable, list
>concatenation does not mutate, and in general adding two things (with +)
>will not mutate either object. Immutable values, by design, do not have
>the same methods and operations as the mutable counterparts (or at least
>the mutating methods of those mutable objects). *That* would be a
>design bug.


You miss my point. Your argument would equally apply to the need for
an integer-specific division operator, for instance. Its all about how
one function reacts in response to varying input. If you pass a
mutable value to a function which expects an immutable one, you get an
error. If you pass an immutable value to a function which expects a
mutable one, you get an error. There is no good reason for a function
to react to the distinction as evidenced by your own observation that
what actually happens (and what should happen) is that you have two
distinct variants of the function.

>> Tell me one case where an object storing values should care about
>> callers mutating values it holds *only* for certain types.

>
>Objects don't *store* values, they *refer* to values. You are still
>thinking like you're in C (or C++). This is why you are having a
>problem.


No it is not. I'm thinking in terms of computer science, in which
terms like 'variable', 'value' and 'assignment' are abstract concepts
independent of the way in which they are implemented in a programming
language.

One way or the other, Python is currently choosing not to respect the
computer science definition of those terms. It may have historic and
backward-compatability reasons, but that does not change the facts.
This deviation from computer science definitions, whatever the excuse,
is arbitrary, confusing and error prone. That is my problem.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
object-like macro used like function-like macro Patrick Kowalzick C++ 5 03-14-2006 03:30 PM
Anything like IPKall for sipgate? John Smith UK VOIP 6 09-20-2005 05:43 PM
Is there anything like Oracle ADF in other Java IDE tools ? krislioe@gmail.com Java 10 06-30-2005 03:27 PM
Re: never heard anything like it in my life? Jumbo C++ 5 01-23-2004 03:18 AM
Re: Anything like Atomica/GuruNet ? Mir Computer Support 1 08-17-2003 12:12 PM



Advertisments