[Python-ideas] New __reference__ hook

Steven D'Aprano steve at pearwood.info
Tue Dec 4 12:14:44 CET 2012


On 04/12/12 20:58, haael at interia.pl wrote:
>
> Hi, guys.
>
> Python 3 is very close to become a holy grail of programming languages in
> the sense that almost everything could be redefined. However, there is
>still one thing missing: the immutable copy-on-assign numeric types.
> Consider this part of code:

I dispute that "everything can be redefined" is the holy grail of
programming languages. If it were, why isn't everyone using Forth?


> a = 1
> b = a
> a += 1
> assert a == b + 1
>
> The object "1" gets assigned to the "a" variable,

Correct, for some definition of "assigned" and "variable".


> then another independent copy gets assigned to the "b" variable,

Completely, utterly wrong.


>then the value in the "a" variable gets modified

Incorrect.


> without affecting the second.
> The problem is - this behaviour can not be recreated in user-defined
>  classes:

Of course it can.

py> from decimal import Decimal  # A pure-Python class, prior to Python 3.3
py> a = Decimal(1)
py> b = a
py> a += 1
py> assert a == b + 1
py> print a, b
2 1

If you prefer another example, use fractions.Fraction, also pure Python
and immutable, with support for augmented assignment.


I don't mean to be rude, or dismissive, but this is pretty basic Python
stuff. Please start with the Python data and execution models:

http://docs.python.org/2/reference/datamodel.html
http://docs.python.org/2/reference/executionmodel.html


although I must admit I don't find either of them especially clear. But
in simple terms, you need to reset your thinking: your assumptions about
what Python does are incorrect.

When you say:

a = 1

you are *binding* the name "a" to the object 1. When you then follow by
saying:

b = a

you bind the name "b" to the *same* object 1. It is not a copy. It is not
a "copy on assignment" or any other clever trick. You can prove to
yourself that they are the same object:


py> a = 1
py> b = a
py> a is b
True
py> id(a), id(b)
(140087472, 140087472)


When you then call

a += 1

this does not modify anything. Int objects (and floats, Decimal, strings,
and many others) are *immutable* -- they cannot be modified. So `a += 1`
creates a new object, 2, and binds it to the name "a". But the binding
from object 1 to name "b" is not touched.

If this is still not clear, I recommend you take the discussion onto one
of the other Python mailing lists, especially tutor at python.org or
python-list at python.org, which are more appropriate for discussing these
things.



-- 
Steven



More information about the Python-ideas mailing list