Re: var or inout parm?

2008-12-13 Thread Aaron Brady
On Dec 12, 7:31 am, Steve Holden  wrote:
> sturlamolden wrote:
> > On Dec 12, 1:56 pm, sturlamolden  wrote:
>
> >> That is because integers are immutable. When x += 1 is done on an int,
> >> there will be a rebinding. But try the same on say, a numpy array, and
> >> the result will be different:
snip

> This was all thrashed out exhaustively in the still-feared call
> semantics thread. Yes, augmented operations work differently on mutable
> and immutable objects. Nothing to see here, move right along ...

Lol!  
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-13 Thread sturlamolden
On 13 Des, 21:26, sturlamolden  wrote:

> Python methods always have a return value, even those that seem to do
> not - they silently return None. Thus, __iadd__ must return self to
> avoid rebinding to None.

Except for immutable types, for which __iadd__ must return a new
instance.




--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-13 Thread sturlamolden
On 13 Des, 02:20, Hrvoje Niksic  wrote:

> > tmp = mytuple.__getitem__(0)
> > tmp = tmp.__iadd__(1)
> > mytuple.__setitem__(0, tmp) # should this always raise an exception?
>
> What do you mean by "a sane parser"?  This is exactly what happens in
> current Python.  

Yes, but Steve Holden was suggesting mytuple.__iadd__ would be
invoked.

> The decision to also rebind
> the result of __i*__ methods continues to baffle me.  

Python methods always have a return value, even those that seem to do
not - they silently return None. Thus, __iadd__ must return self to
avoid rebinding to None.


--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-13 Thread Hrvoje Niksic
Marc 'BlackJack' Rintsch  writes:

> On Sat, 13 Dec 2008 02:20:59 +0100, Hrvoje Niksic wrote:
>
>> Saner (in this respect) behavior in the tuple example would require
>> a different protocol.  I don't understand why Python doesn't just
>> call __iadd__ for side effect if it exists.  The decision to also
>> rebind the result of __i*__ methods continues to baffle me.  I
>> guess it is a result of a desire to enable the __i*__ methods to
>> punt and return a different instance after all, but if so, that
>> design decision brings more problems than benefits.
>
> How often do you use ``+=`` with mutable objects?  I use it very
> often with number types and sometimes with tuples, and there
> rebinding is necessary.  If I couldn't use it in this way: ``x = 0;
> x += z``, I'd call that a bad design decision.  It would be a quite
> useless operator then.

Marc, I agree with you, I wasn't arguing that += shouldn't work for
immutable objects.  If an object doesn't support __iadd__ at all (as
is already the case for numbers, strings, etc.), += should fall back
to __add__ followed by assignment.  My point is that, *if they do*, it
would be better to just use __iadd__ and not attempt to also rebind.
Again, in pseudocode, I'd expect A += x to be implemented as:

lhsobj = A
if hasattr(lhsobj, '__iadd__'):
lhsobj.__iadd__(x) # lhsobj has __iadd__, just use it
else:
A = lhsobj.__add__(x)  # fails if __add__ is not present either

That way tupleobj[0] += blah would work just fine for mutable objects
and would throw an exception for immutable objects.  The current
situation where += first modifies the mutable object, and *then*
throws an exception feels like a design glitch.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-13 Thread Marc 'BlackJack' Rintsch
On Sat, 13 Dec 2008 02:20:59 +0100, Hrvoje Niksic wrote:

> Saner (in this respect) behavior in the tuple example would require a
> different protocol.  I don't understand why Python doesn't just call
> __iadd__ for side effect if it exists.  The decision to also rebind the
> result of __i*__ methods continues to baffle me.  I guess it is a result
> of a desire to enable the __i*__ methods to punt and return a different
> instance after all, but if so, that design decision brings more problems
> than benefits.

How often do you use ``+=`` with mutable objects?  I use it very often 
with number types and sometimes with tuples, and there rebinding is 
necessary.  If I couldn't use it in this way:  ``x = 0; x += z``, I'd 
call that a bad design decision.  It would be a quite useless operator 
then.

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Hrvoje Niksic
sturlamolden  writes:

> What? Take a look at the code again:
>
> mytuple[0] += 1
>
> should never attempt an __iadd__ on mytuple.
>
> A sane parser would see this as:
>
> tmp = mytuple.__getitem__(0)
> tmp = tmp.__iadd__(1)
> mytuple.__setitem__(0, tmp) # should this always raise an exception?

What do you mean by "a sane parser"?  This is exactly what happens in
current Python.  Since tuple's __setitem__ always raises an exception
(and that is by design and not likely to change), everything is sane.

Saner (in this respect) behavior in the tuple example would require a
different protocol.  I don't understand why Python doesn't just call
__iadd__ for side effect if it exists.  The decision to also rebind
the result of __i*__ methods continues to baffle me.  I guess it is a
result of a desire to enable the __i*__ methods to punt and return a
different instance after all, but if so, that design decision brings
more problems than benefits.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Steven D'Aprano
On Fri, 12 Dec 2008 08:43:31 -0800, sturlamolden wrote:

> On Dec 12, 5:13 pm, Steve Holden  wrote:
> 
>> > It should be the tuple's __setitem__ that was invoked here, not
>> > __iadd__, or the parser is faulty.
>>
>> OK, so now you are proposing to alter the parser, and possibly the
>> implementation of the INPLACE_ADD opcode in eval.c, so can you give us
>> the patch for those, please?
> 
> What? Take a look at the code again:
> 
> mytuple[0] += 1
> 
> should never attempt an __iadd__ on mytuple.
> 
> A sane parser would see this as:
> 
> tmp = mytuple.__getitem__(0)
> tmp = tmp.__iadd__(1)
> mytuple.__setitem__(0, tmp) # should this always raise an exception?

It is quite problematic if you do that. You've already pointed that out 
yourself, by asking if "should this always raise an exception?". With the 
behaviour you're asking for, there's ambiguity is what is allowed and 
what isn't. You can try making __setitem__ cleverer, as in your earlier 
post, but then:

t = (1, 2, 3)
t[0] += x

sometimes succeeds, sometimes fails, depending on the value of x.

And worse:

t[0] = y

also sometimes succeeds.

It's not clear that those occasional successes are actively harmful, but 
nor is it clear that prohibiting them is harmful either. The best you get 
from it is the ability to mutate mutable items in a tuple, but you can do 
that already:

t = ([], None)
x = t[0]
x += ["mutated"]

So the current tuple implementation gives us consistent behaviour and 
simplicity without preventing you from mutating elements if you really 
want to. The only real cost is if you do this:

t[0] += ["mutated"]

you get an error and a mutation. Certainly a gotcha, but I wouldn't 
describe it as a bug: it's pretty much unavoidable if you want to avoid 
treating tuples as a special case.



>> Discussion of such behavior as a "bug" is also pejorative, since the
>> current semantics are the way they are by design.
> 
> Right, this bug is by design. You learned that phrase from a guy in
> Redmond?

No. It merely means that just because you think it is a bug doesn't make 
it so. It may even mean that there is no perfect solution, that *any* 
behaviour on tuples containing mutable objects will be considered broken 
by some people under some circumstances.

Trade-offs in software design are inevitable. There's little gain from 
your proposal, and some cost, and the problem you are trying to solve 
isn't a problem in practice. So if it's a bug, it's an insignificant one, 
not worth fixing because the fix will invariably cause more problems than 
the bug.



-- 
Steven
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Chris Rebert
On Fri, Dec 12, 2008 at 4:56 AM, sturlamolden  wrote:
> On Dec 12, 1:44 pm, "Chris Rebert"  wrote:
>
>> Python begs to differ, as those two statements are both semantically
>> identical in this case:
>
> That is because integers are immutable. When x += 1 is done on an int,
> there will be a rebinding. But try the same on say, a numpy array, and
> the result will be different:

Yes, I know that. Did you not read the end of my email? Here it is again:

"""
If you were talking about lists rather than integers though, you'd be
absolutely correct, as the += ends up being a method call to __iadd__
instead of a plain assignment.
"""

Cheers,
Chris

-- 
Follow the path of the Iguana...
http://rebertia.com
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Arnaud Delobelle
Marc 'BlackJack' Rintsch  writes:

> On Fri, 12 Dec 2008 07:56:58 -0800, sturlamolden wrote:
>
>> On Dec 12, 4:55 pm, sturlamolden  wrote:
>> 
>>> def __setitem__(self, index, value):
>>>if _buf[index] is not value: # given that _buf is the tuple's
>>> internal buffer
>>>   raise TypeError, 'tuple' object does not support item
>>> assignment
>> 
>> blæh, that should be self._buf[index]
>
> But then the error message is not true anymore because tuples *would* 
> support item assignment when the old and new value are the same.  Which 
> leads to strange things like code that may or may not raise that 
> exception, depending on implementation details:
>
> t = (1, 2)
> t[0] = 1   # Maybe okay -- maybe not.
> t[1] += 0  # Same here.
>
> I'd find that quite odd.
>
> Ciao,
>   Marc 'BlackJack' Rintsch

What I find a bit annoying is when you get both

* an exception
* a mutation

E.g.

>>> t[1] *= 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Now is t the same as before?  Sometimes it is:

>>> t
(1, 2)
>>> t[1] *= 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2)

Sometimes not:

>>> t
(1, [2])
>>> t[1] *= 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment
>>> t
(1, [2, 2])

I agree it's not a bug, but I never feel comfortable with it.

-- 
Arnaud
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 5:13 pm, Steve Holden  wrote:

> OK, so now you are proposing to alter the parser, and possibly the
> implementation of the INPLACE_ADD opcode in eval.c, so can you give us
> the patch for those, please?

That is not where the problem resides.

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Steve Holden
sturlamolden wrote:
> On Dec 12, 5:13 pm, Steve Holden  wrote:
> 
>>> It should be the tuple's __setitem__ that was invoked here, not
>>> __iadd__, or the parser is faulty.
>> OK, so now you are proposing to alter the parser, and possibly the
>> implementation of the INPLACE_ADD opcode in eval.c, so can you give us
>> the patch for those, please?
> 
> What? Take a look at the code again:
> 
> mytuple[0] += 1
> 
> should never attempt an __iadd__ on mytuple.
> 
> A sane parser would see this as:
> 
> tmp = mytuple.__getitem__(0)
> tmp = tmp.__iadd__(1)
> mytuple.__setitem__(0, tmp) # should this always raise an exception?
> 
> 
>> Discussion of such behavior as a "bug" is also pejorative, since the
>> current semantics are the way they are by design.
> 
> Right, this bug is by design. You learned that phrase from a guy in
> Redmond?
> 
"It's not a bug, it's a feature" predates Microsoft by several years.

If I say you are ugly, that doesn't make it true. Neither does your
calling this a bug make it a bug.

The fact is that Python doesn't behave the way you want it to. If your
friend doesn't want to do what you do, does that make it a bug in his
behavior. You're being a little juvenile here.

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

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 5:13 pm, Steve Holden  wrote:

> > It should be the tuple's __setitem__ that was invoked here, not
> > __iadd__, or the parser is faulty.
>
> OK, so now you are proposing to alter the parser, and possibly the
> implementation of the INPLACE_ADD opcode in eval.c, so can you give us
> the patch for those, please?

What? Take a look at the code again:

mytuple[0] += 1

should never attempt an __iadd__ on mytuple.

A sane parser would see this as:

tmp = mytuple.__getitem__(0)
tmp = tmp.__iadd__(1)
mytuple.__setitem__(0, tmp) # should this always raise an exception?


> Discussion of such behavior as a "bug" is also pejorative, since the
> current semantics are the way they are by design.

Right, this bug is by design. You learned that phrase from a guy in
Redmond?



--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Marc 'BlackJack' Rintsch
On Fri, 12 Dec 2008 07:56:58 -0800, sturlamolden wrote:

> On Dec 12, 4:55 pm, sturlamolden  wrote:
> 
>> def __setitem__(self, index, value):
>>if _buf[index] is not value: # given that _buf is the tuple's
>> internal buffer
>>   raise TypeError, 'tuple' object does not support item
>> assignment
> 
> blæh, that should be self._buf[index]

But then the error message is not true anymore because tuples *would* 
support item assignment when the old and new value are the same.  Which 
leads to strange things like code that may or may not raise that 
exception, depending on implementation details:

t = (1, 2)
t[0] = 1   # Maybe okay -- maybe not.
t[1] += 0  # Same here.

I'd find that quite odd.

Ciao,
Marc 'BlackJack' Rintsch

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Steve Holden
sturlamolden wrote:
> On Dec 12, 3:54 pm, Steve Holden  wrote:
[...]
>> The interpreter "should not" have a GIL.
> 
>> The tuple "should" check that
>> it is actually being mutated. How?
> 
> In Python it would be something similar to:
> 
> def __setitem__(self, index, value):
>if _buf[index] is not value: # given that _buf is the tuple's
> internal buffer
>   raise TypeError, 'tuple' object does not support item
> assignment
> 
> It should be the tuple's __setitem__ that was invoked here, not
> __iadd__, or the parser is faulty.
> 
OK, so now you are proposing to alter the parser, and possibly the
implementation of the INPLACE_ADD opcode in eval.c, so can you give us
the patch for those, please?

This is exactly the point I was trying to make. It's easy to stand on
the sidelines and make sensible- or even intelligent-sounding
suggestions about how to change Python. But inside the interpreter
there's a maze of twisty little passages all alike (or similar
complexity), and hand-waving doesn't get you anywhere.

Discussion of such behavior as a "bug" is also pejorative, since the
current semantics are the way they are by design. You are therefore
disagreeing with the design of Python rather than discussing a bug in
its implementation.

That also raises the issues of how you get Jython and IronPython to
implement the same semantics, and whether you care about the millions of
lines of code that already assumes the current behavior.

You've got a lot of work to do ...

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

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 4:55 pm, sturlamolden  wrote:

> def __setitem__(self, index, value):
>if _buf[index] is not value: # given that _buf is the tuple's
> internal buffer
>   raise TypeError, 'tuple' object does not support item
> assignment

blæh, that should be self._buf[index]




--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 3:54 pm, Steve Holden  wrote:
> sturlamolden wrote:
> > On Dec 12, 3:08 pm, Marc 'BlackJack' Rintsch  wrote:
>
> >> No bug because a mutation *is* attempted.  ``a += x`` calls `a.__iadd__`
> >> which *always* returns the result which is *always* rebound to the name
> >> `a`.  Even with mutable objects where `__iadd__()` simply returns
> >> `self`!
>
> > No, a mutation is not attempted, even if __iadd__() always returns a
> > value. If a rebinding of a member to the same member is attempted, the
> > tuple should not raise an exception. The tuple should check that it is
> > actually being *mutated* before it raises any exception. There is an
> > attempted write to the tuple, but not an attempted mutation of the
> > tuple. The tuple should tell the difference. Immutability does not
> > imply inwriteability, if the write operation changes nothing. But the
> > tuple raises an exception on any write attempt.
>
> OK, so if you regard the current behavior as a bug explain how to modify
> the tuple's __iadd__ method and the coding of the INPLACE_ADD operator.
> At least in pseudocode.
>
> Criticism is easy. Now demonstrate that it's *informed* criticism.
> Enough of the "should". I am always suspicious of suggestions that say
> what the interpreter "should" or "should not" do. It makes it sound as
> though you can wave a magic wand to achieve the desired behavior.


> The interpreter "should not" have a GIL.

> The tuple "should" check that
> it is actually being mutated. How?

In Python it would be something similar to:

def __setitem__(self, index, value):
   if _buf[index] is not value: # given that _buf is the tuple's
internal buffer
  raise TypeError, 'tuple' object does not support item
assignment

It should be the tuple's __setitem__ that was invoked here, not
__iadd__, or the parser is faulty.


S.M.



--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Hrvoje Niksic
sturlamolden  writes:

> On Dec 12, 3:08 pm, Marc 'BlackJack' Rintsch  wrote:
>
>> No bug because a mutation *is* attempted.  ``a += x`` calls `a.__iadd__`
>> which *always* returns the result which is *always* rebound to the name
>> `a`.  Even with mutable objects where `__iadd__()` simply returns
>> `self`!
>
> No, a mutation is not attempted, even if __iadd__() always returns a
> value.

Mutation is attempted.  A += x (where "A" could be anything valid at
the left-hand side of assignment, including item subscript) is not
implemented intuitivaly, as:

if hasattr(b, '__iadd__'):
A.__iadd__(x)   # ignore return value
else:
A = A.__add__(x)

It is implemented as something like:

if hasattr(b, '__iadd__'):
newval = A.__iadd__(x)
else:
newval = A.__add__(x)
A = newval

So the only difference between __add__ and __iadd__ is that __iadd__
is only consulted on +=, where as __add__ is consulted on both + and
+= (in the latter case only if __iadd__ is missing).

> The tuple should check that it is
> actually being *mutated* before it raises any exception.

Tuple has no way to check that.  What tuple sees is only the last
line:

t[0] = newval

At that point, the information about what is really going on is long
lost.  The only thing tuple could do is detect that the same object is
being written that's already there, but tuple doesn't do that by
design.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Steve Holden
sturlamolden wrote:
> On Dec 12, 3:08 pm, Marc 'BlackJack' Rintsch  wrote:
> 
>> No bug because a mutation *is* attempted.  ``a += x`` calls `a.__iadd__`
>> which *always* returns the result which is *always* rebound to the name
>> `a`.  Even with mutable objects where `__iadd__()` simply returns
>> `self`!
> 
> No, a mutation is not attempted, even if __iadd__() always returns a
> value. If a rebinding of a member to the same member is attempted, the
> tuple should not raise an exception. The tuple should check that it is
> actually being *mutated* before it raises any exception. There is an
> attempted write to the tuple, but not an attempted mutation of the
> tuple. The tuple should tell the difference. Immutability does not
> imply inwriteability, if the write operation changes nothing. But the
> tuple raises an exception on any write attempt.
> 
OK, so if you regard the current behavior as a bug explain how to modify
the tuple's __iadd__ method and the coding of the INPLACE_ADD operator.
At least in pseudocode.

Criticism is easy. Now demonstrate that it's *informed* criticism.
Enough of the "should". I am always suspicious of suggestions that say
what the interpreter "should" or "should not" do. It makes it sound as
though you can wave a magic wand to achieve the desired behavior.

The interpreter "should not" have a GIL. The tuple "should" check that
it is actually being mutated. How?

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

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 3:08 pm, Marc 'BlackJack' Rintsch  wrote:

> No bug because a mutation *is* attempted.  ``a += x`` calls `a.__iadd__`
> which *always* returns the result which is *always* rebound to the name
> `a`.  Even with mutable objects where `__iadd__()` simply returns
> `self`!

No, a mutation is not attempted, even if __iadd__() always returns a
value. If a rebinding of a member to the same member is attempted, the
tuple should not raise an exception. The tuple should check that it is
actually being *mutated* before it raises any exception. There is an
attempted write to the tuple, but not an attempted mutation of the
tuple. The tuple should tell the difference. Immutability does not
imply inwriteability, if the write operation changes nothing. But the
tuple raises an exception on any write attempt.














--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Hrvoje Niksic
sturlamolden  writes:

> Actually I would consider this to be a bug. The tuple is immutable,
> but no mutation of the tuple is ever attempted.

That's a common misconception about how += works in Python.  It simply
*always* rebinds.  Once you grok that, everything else follows.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Marc 'BlackJack' Rintsch
On Fri, 12 Dec 2008 05:39:35 -0800, sturlamolden wrote:

> On Dec 12, 2:34 pm, Hrvoje Niksic  wrote:
> 
>> >>> import numpy
>> >>> t = (numpy.zeros(10),)
>> >>> t
>>
>> (array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),)>>> t[0] +=
>> 1
>>
>> Traceback (most recent call last):
>>   File "", line 1, in 
>> TypeError: 'tuple' object does not support item assignment
>>
>> Of course, the side effect occurs before the exception, so:
>>
>> >>> t[0]
> 
>> array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])
> 
> 
> Actually I would consider this to be a bug. The tuple is immutable, but
> no mutation of the tuple is ever attempted.

No bug because a mutation *is* attempted.  ``a += x`` calls `a.__iadd__` 
which *always* returns the result which is *always* rebound to the name 
`a`.  Even with mutable objects where `__iadd__()` simply returns 
`self`!  It has to be this way because the compiler has no idea if the 
object bound to `a` will be mutable or immutable when the code actually 
runs.

In [252]: def f(a, x):
   .: a += x
   .:

In [253]: dis.dis(f)
  2   0 LOAD_FAST0 (a)
  3 LOAD_FAST1 (x)
  6 INPLACE_ADD
  7 STORE_FAST   0 (a)
 10 LOAD_CONST   0 (None)
 13 RETURN_VALUE

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 2:34 pm, Hrvoje Niksic  wrote:

> >>> import numpy
> >>> t = (numpy.zeros(10),)
> >>> t
>
> (array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),)>>> t[0] += 1
>
> Traceback (most recent call last):
>   File "", line 1, in 
> TypeError: 'tuple' object does not support item assignment
>
> Of course, the side effect occurs before the exception, so:
>
> >>> t[0]

> array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])


Actually I would consider this to be a bug. The tuple is immutable,
but no mutation of the tuple is ever attempted.

Sturla Molden



--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Hrvoje Niksic
sturlamolden  writes:

> On Dec 12, 1:44 pm, "Chris Rebert"  wrote:
>
>> Python begs to differ, as those two statements are both semantically
>> identical in this case:
>
> That is because integers are immutable. When x += 1 is done on an int,
> there will be a rebinding. But try the same on say, a numpy array, and
> the result will be different:

The result will be different, but a still occurs!  You usually don't
notice it because augmented assignments with side effect are normally
careful to return the same object, so rebinding is a no-op.  But in
some cases, that can byte you.  For example, tupleobj[0] += 1 raises
an exception even when tupleobj[0] is mutable.  Taking the numpy
example:

>>> import numpy
>>> t = (numpy.zeros(10),)
>>> t
(array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),)
>>> t[0] += 1
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Of course, the side effect occurs before the exception, so:

>>> t[0]
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Steve Holden
sturlamolden wrote:
> On Dec 12, 1:56 pm, sturlamolden  wrote:
> 
>> That is because integers are immutable. When x += 1 is done on an int,
>> there will be a rebinding. But try the same on say, a numpy array, and
>> the result will be different:
> 
> 
> And a consequence of this is, if you have a function like
> 
> def foobar(x):
>x += 1
> 
> then the parameter x will be modified given that x have mutable type.
> 
> However, if we have a function like
> 
> def foobar(x):
>x = x + 1
> 
> then x will not be modified, mutable or not.
> 
> (Well, you could abuse operator overlaoding to make unexpected side
> effects in the latter case. But except for such insanity it will not
> have side-effects.)
> 
This was all thrashed out exhaustively in the still-feared call
semantics thread. Yes, augmented operations work differently on mutable
and immutable objects. Nothing to see here, move right along ...

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

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 1:56 pm, sturlamolden  wrote:

> That is because integers are immutable. When x += 1 is done on an int,
> there will be a rebinding. But try the same on say, a numpy array, and
> the result will be different:


And a consequence of this is, if you have a function like

def foobar(x):
   x += 1

then the parameter x will be modified given that x have mutable type.

However, if we have a function like

def foobar(x):
   x = x + 1

then x will not be modified, mutable or not.

(Well, you could abuse operator overlaoding to make unexpected side
effects in the latter case. But except for such insanity it will not
have side-effects.)








--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 12, 1:44 pm, "Chris Rebert"  wrote:

> Python begs to differ, as those two statements are both semantically
> identical in this case:

That is because integers are immutable. When x += 1 is done on an int,
there will be a rebinding. But try the same on say, a numpy array, and
the result will be different:

>>> import numpy
>>> x = numpy.zeros(10)
>>> id(x)
19504848
>>> x += 1
>>> id(x)
19504848
>>> x = x + 1
>>> id(x)
10451488


Whereas:

>>> x = 1
>>> id(x)
10051256
>>> x += 1
>>> id(x)
10051244
>>> x = x + 1
>>> id(x)
10051232




--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread Chris Rebert
On Fri, Dec 12, 2008 at 4:34 AM, sturlamolden  wrote:

> You cannot modify parameters by rebinding. x = x + 1 is a rebinding. x
> += 1 is not.

Python begs to differ, as those two statements are both semantically
identical in this case:

Python 2.6 (r26:66714, Nov 18 2008, 21:48:52)
[GCC 4.0.1 (Apple Inc. build 5484)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = 2
>>> id (x)
8405372
>>> x += 1
>>> id(x)
8405360
>>> x = x + 1
>>> id(x)
8405348

If you were talking about lists rather than integers though, you'd be
absolutely correct, as the += ends up being a method call to __iadd__
instead of a plain assignment.

Cheers,
Chris

-- 
Follow the path of the Iguana...
http://rebertia.com
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-12 Thread sturlamolden
On Dec 7, 9:54 am, m...@pixar.com wrote:

> How can I make a "var" parm, where the called function can modify
> the value of the parameter in the caller?
>
> def f(x):
> x = x + 1

Short ansver:

You can modify function parameters if they are mutable. If they are
immutable any attempt to modify the parameter will trigger a copy.

You cannot modify parameters by rebinding. x = x + 1 is a rebinding. x
+= 1 is not.

If you need to modify immutable parameters or do the modification by
rebinding, pass the variable back. Python allows multiple return
values.
















--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-11 Thread mh
J. Clifford Dyer  wrote:
> Just google for call-by-object, and ignore the hell out of that thread.

Now I've got to go read it! ;-)

-- 
Mark Harrison
Pixar Animation Studios
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-11 Thread Bruno Desthuilliers

Joe Strout a écrit :

On Dec 10, 2008, at 4:29 PM, J. Clifford Dyer wrote:


[EMAIL PROTECTED] wrote:


How can I make a "var" parm, where the called function can modify
the value of the parameter in the caller?


See Also: the earlier heated debate thread over what evaluation
strategy Python uses (Survey says!: call-by-object).



Oh dear God.  PLEASE don't see also that thread.  That way lies madness.
Just google for call-by-object, and ignore the hell out of that thread.


Agreed on that point!

Anyway, to the OP, see  


Do you really want to start a new flame war, Joe ?-)

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-10 Thread Joe Strout

On Dec 10, 2008, at 4:29 PM, J. Clifford Dyer wrote:


[EMAIL PROTECTED] wrote:


How can I make a "var" parm, where the called function can modify
the value of the parameter in the caller?


See Also: the earlier heated debate thread over what evaluation
strategy Python uses (Survey says!: call-by-object).



Oh dear God.  PLEASE don't see also that thread.  That way lies  
madness.
Just google for call-by-object, and ignore the hell out of that  
thread.


Agreed on that point!

Anyway, to the OP, see  for  
a detailed explanation of why you can't do quite what you're asking  
for in Python (or Java, for that matter).


Best,
- Joe

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-10 Thread J. Clifford Dyer
On Mon, 2008-12-08 at 00:57 -0800, Chris Rebert wrote:
> On Mon, Dec 8, 2008 at 12:26 AM, Bruno Desthuilliers
> <[EMAIL PROTECTED]> wrote:
> > Colin J. Williams a écrit :
> >>
> >> [EMAIL PROTECTED] wrote:
> >>>
> >>> How can I make a "var" parm, where the called function can modify
> >>> the value of the parameter in the caller?
> >>>
> >>> def f(x):
> >>>x = x + 1
> >>>
> >>> n = 1
> >>> f(n)
> >>> # n should now be 2
> >>>
> >>> Many TIA!!
> >>> Mark
> >>>
> >>>
> >>
> >> Why not run it and see?
> >>
> >> Your function returns None.
> >>
> >> The function in effect takes a copy of n.
> >
> > Nope, it takes the object bound to global name 'n'.
> 
> See Also: the earlier heated debate thread over what evaluation
> strategy Python uses (Survey says!: call-by-object).
> 

Oh dear God.  PLEASE don't see also that thread.  That way lies madness.
Just google for call-by-object, and ignore the hell out of that thread.



> Cheers,
> Chris
> 

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-10 Thread mh
Chris Rebert <[EMAIL PROTECTED]> wrote:
> Not directly possible or encouraged. You can emulate it by sticking
> the value in a container object (e.g. list) though:

Thanks, that's just what I needed.  I'm using this to monkeypatch
a test driver into some code that I can't touch, otherwise 
I would just have the function return a tuple with the replacement
values.

Cheers!
Mark

-- 
Mark Harrison
Pixar Animation Studios
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-08 Thread Aaron Brady
On Dec 7, 2:54 am, [EMAIL PROTECTED] wrote:
> How can I make a "var" parm, where the called function can modify
> the value of the parameter in the caller?
>
> def f(x):
>     x = x + 1
>
> n = 1
> f(n)
> # n should now be 2

You can't.  'n' would need a 'set_to' method, which it doesn't have.
Otherwise, that's not what the equal sign does.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-08 Thread Chris Rebert
On Mon, Dec 8, 2008 at 12:26 AM, Bruno Desthuilliers
<[EMAIL PROTECTED]> wrote:
> Colin J. Williams a écrit :
>>
>> [EMAIL PROTECTED] wrote:
>>>
>>> How can I make a "var" parm, where the called function can modify
>>> the value of the parameter in the caller?
>>>
>>> def f(x):
>>>x = x + 1
>>>
>>> n = 1
>>> f(n)
>>> # n should now be 2
>>>
>>> Many TIA!!
>>> Mark
>>>
>>>
>>
>> Why not run it and see?
>>
>> Your function returns None.
>>
>> The function in effect takes a copy of n.
>
> Nope, it takes the object bound to global name 'n'.

See Also: the earlier heated debate thread over what evaluation
strategy Python uses (Survey says!: call-by-object).

Cheers,
Chris

-- 
Follow the path of the Iguana...
http://rebertia.com

>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-08 Thread Bruno Desthuilliers

Colin J. Williams a écrit :

[EMAIL PROTECTED] wrote:

How can I make a "var" parm, where the called function can modify
the value of the parameter in the caller?

def f(x):
x = x + 1

n = 1
f(n)
# n should now be 2

Many TIA!!
Mark




Why not run it and see?

Your function returns None.

The function in effect takes a copy of n.


Nope, it takes the object bound to global name 'n'.

--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-07 Thread Colin J. Williams

[EMAIL PROTECTED] wrote:

How can I make a "var" parm, where the called function can modify
the value of the parameter in the caller?

def f(x):
x = x + 1

n = 1
f(n)
# n should now be 2

Many TIA!!
Mark




Why not run it and see?

Your function returns None.

The function in effect takes a copy of 
n.  n is not changed.


Colin W.
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-07 Thread Steven D'Aprano
On Sun, 07 Dec 2008 08:54:46 +, mh wrote:

> How can I make a "var" parm, where the called function can modify the
> value of the parameter in the caller?

By using another language.

> def f(x):
> x = x + 1
> 
> n = 1
> f(n)
> # n should now be 2

Python doesn't work like that. You should read this:

http://effbot.org/zone/python-objects.htm


Some work arounds, in order from worst-to-best:


(1) Use a hard-coded global name:


x = 1

def f():
global x
x = x + 1

f()
assert x == 2


(2) Wrap the value you want to change in a list, then modify the list in 
place.

n = [1]

def f(alist):
alist[0] = alist[0] + 1

f(n)
assert n[0] == 2


(4) Just use an ordinary function. Functions can return multiple values.

n = 1

def f(x):
return (x+1, 99)

n, y = f(n)
assert y == 99
assert n == 2


(5) Find another way to solve your problem.

Why do you think you need var parameters? What problem are you hoping to 
solve by using them? As a former Pascal programmer, I missed var 
parameters at first, but now I don't.




-- 
Steven
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-07 Thread Diez B. Roggisch

[EMAIL PROTECTED] schrieb:

How can I make a "var" parm, where the called function can modify
the value of the parameter in the caller?

def f(x):
x = x + 1

n = 1
f(n)
# n should now be 2


Chris showed one way, another is simply returning it. As python can 
return ad-hoc created tuples & unpack them, some C++-wrappers for 
example treat out/inout vars like this:



def foo(in, inout):
return inout, out1, out2


x, y, z = foo(a, x)

Obviously you are responsible for properly assigning the returned inout 
to the right name again.


Diez
--
http://mail.python.org/mailman/listinfo/python-list


Re: var or inout parm?

2008-12-07 Thread Chris Rebert
On Sun, Dec 7, 2008 at 12:54 AM,  <[EMAIL PROTECTED]> wrote:
> How can I make a "var" parm, where the called function can modify
> the value of the parameter in the caller?

Not directly possible or encouraged. You can emulate it by sticking
the value in a container object (e.g. list) though:

def f(x):
x[0] += 1 #non-augmented assignment would work too

n = [1]
f(n)
print n[0] #==> 2

Cheers,
Chris

-- 
Follow the path of the Iguana...
http://rebertia.com

>
> def f(x):
>x = x + 1
>
> n = 1
> f(n)
> # n should now be 2
>
> Many TIA!!
> Mark
>
>
> --
> Mark Harrison
> Pixar Animation Studios
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
http://mail.python.org/mailman/listinfo/python-list