So where I’m rewriting some Python code in a low level
language, I can’t assume that the two objects are equal
because that equality will not remain if either is reassigned.
|Falsex =( 1, 2 )
y =( 1, 2 )
x is y
|Truex == y
|Truex =( 1, 2 )
y = x
x is y
|Truex == y
|Truex =( 1, 2 )
y =( 1, 2 )
x == y
a = x
b = y
del x
del y
Thanks for your comments. I'd like to make one small point. You say:matrix.
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way."
But where they have been set to the same object, an operation on one will affect the other as long as they are equal (in Python). So I will have to conform them in those cases because Python will reflect any math operation in both the array and the
I am writing a spot speedup in assembly language for a short but computation-intensive Python loop, and I discovered something about Python array handling that I would like to clarify.reflected in both arrays because they are now pointing to the same array:
For a simplified example, I created a matrix mx1 and assigned the array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in assembly or C, I can just borrow the pointer to row 3 for the array arr1, on the assumption that they will continue to point to the same object. Then when I do any math operations in arr1 it will be
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any subsequent operations in arr1 will not affect mx1.
So where I’m rewriting some Python code in a low level language, I can’t assume that the two objects are equal because that equality will not remain if either is reassigned. So if I do some operation on one array I have to conform the two arraysfor as long as they remain equal, I can’t just do it in one operation because I can’t rely on the objects remaining equal.
Is my understanding of this correct? Is there anything I’m missing?
On Wed, 11 Jan 2023 at 07:14, Jen Kris via Python-list <python-list@python.org> wrote:reflected in both arrays because they are now pointing to the same array:
I am writing a spot speedup in assembly language for a short but computation-intensive Python loop, and I discovered something about Python array handling that I would like to clarify.
For a simplified example, I created a matrix mx1 and assigned the array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in assembly or C, I can just borrow the pointer to row 3 for the array arr1, on the assumption that they will continue to point to the same object. Then when I do any math operations in arr1 it will be
for as long as they remain equal, I can’t just do it in one operation because I can’t rely on the objects remaining equal.
That's not an optimization; what you've done is set arr1 to be a
reference to that object.
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any subsequent operations in arr1 will not affect mx1.
Yep, you have just set arr1 to be a completely different object.
So where I’m rewriting some Python code in a low level language, I can’t assume that the two objects are equal because that equality will not remain if either is reassigned. So if I do some operation on one array I have to conform the two arrays
Is my understanding of this correct? Is there anything I’m missing?
Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
But where they have been set to the same object, an operation on one will affect the other as long as they are equal (in Python).As long as they are *identical*, not equal. Identical as in having the
Thanks for your comments. I'd like to make one small point. You say:matrix.
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way."
But where they have been set to the same object, an operation on one will affect the other as long as they are equal (in Python). So I will have to conform them in those cases because Python will reflect any math operation in both the array and the
Jan 10, 2023, 12:28 by rosuav@gmail.com:reflected in both arrays because they are now pointing to the same array:
On Wed, 11 Jan 2023 at 07:14, Jen Kris via Python-list
<python-list@python.org> wrote:
I am writing a spot speedup in assembly language for a short but computation-intensive Python loop, and I discovered something about Python array handling that I would like to clarify.
For a simplified example, I created a matrix mx1 and assigned the array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in assembly or C, I can just borrow the pointer to row 3 for the array arr1, on the assumption that they will continue to point to the same object. Then when I do any math operations in arr1 it will be
for as long as they remain equal, I can’t just do it in one operation because I can’t rely on the objects remaining equal.
That's not an optimization; what you've done is set arr1 to be a
reference to that object.
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any subsequent operations in arr1 will not affect mx1.
Yep, you have just set arr1 to be a completely different object.
So where I’m rewriting some Python code in a low level language, I can’t assume that the two objects are equal because that equality will not remain if either is reassigned. So if I do some operation on one array I have to conform the two arrays
Is my understanding of this correct? Is there anything I’m missing?
Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Thanks for your comments. I'd like to make one small point. You say:matrix.
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way."
But where they have been set to the same object, an operation on one will affect the other as long as they are equal (in Python). So I will have to conform them in those cases because Python will reflect any math operation in both the array and the
On 2023-01-10 20:41, Jen Kris via Python-list wrote:
It's not a 2D matrix, it's a 1D list containing references to 1D lists,
Thanks for your comments. I'd like to make one small point. You say:
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way."
But where they have been set to the same object, an operation on one
will affect the other as long as they are equal (in Python). So I
will have to conform them in those cases because Python will reflect
any math operation in both the array and the matrix.
each of which contains references to Python ints.
In CPython, references happen to be pointers, but that's just an implementation detail.
Jan 10, 2023, 12:28 by rosuav@gmail.com:
On Wed, 11 Jan 2023 at 07:14, Jen Kris via Python-list
<python-list@python.org> wrote:
I am writing a spot speedup in assembly language for a short but
computation-intensive Python loop, and I discovered something about
Python array handling that I would like to clarify.
For a simplified example, I created a matrix mx1 and assigned the
array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in assembly or C, I can
just borrow the pointer to row 3 for the array arr1, on the
assumption that they will continue to point to the same object.
Then when I do any math operations in arr1 it will be reflected in
both arrays because they are now pointing to the same array:
That's not an optimization; what you've done is set arr1 to be a
reference to that object.
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any subsequent operations
in arr1 will not affect mx1.
Yep, you have just set arr1 to be a completely different object.
So where I’m rewriting some Python code in a low level language, I
can’t assume that the two objects are equal because that equality
will not remain if either is reassigned. So if I do some operation
on one array I have to conform the two arrays for as long as they
remain equal, I can’t just do it in one operation because I can’t
rely on the objects remaining equal.
Is my understanding of this correct? Is there anything I’m missing? >>>>
Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Just to add a possibly picky detail to what others have said, Python
does not have an "array" type. It has a "list" type, as well as some
other, not necessarily mutable, sequence types.
Just to add a possibly picky detail to what others have said, Python does not have an "array" type. It has a "list" type, as well as some other, not necessarily mutable, sequence types.that for many years.
If you want to speed up list and matrix operations, you might use NumPy. Its arrays and matrices are heavily optimized for fast processing and provide many useful operations on them. No use calling out to C code yourself when NumPy has been refining
On 1/10/2023 4:10 PM, MRAB wrote:matrix.
On 2023-01-10 20:41, Jen Kris via Python-list wrote:
Thanks for your comments. I'd like to make one small point. You say: >>>
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way."
But where they have been set to the same object, an operation on one will affect the other as long as they are equal (in Python). So I will have to conform them in those cases because Python will reflect any math operation in both the array and the
reflected in both arrays because they are now pointing to the same array:It's not a 2D matrix, it's a 1D list containing references to 1D lists, each of which contains references to Python ints.
In CPython, references happen to be pointers, but that's just an implementation detail.
Jan 10, 2023, 12:28 by rosuav@gmail.com:
On Wed, 11 Jan 2023 at 07:14, Jen Kris via Python-list
<python-list@python.org> wrote:
I am writing a spot speedup in assembly language for a short but computation-intensive Python loop, and I discovered something about Python array handling that I would like to clarify.
For a simplified example, I created a matrix mx1 and assigned the array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in assembly or C, I can just borrow the pointer to row 3 for the array arr1, on the assumption that they will continue to point to the same object. Then when I do any math operations in arr1 it will be
arrays for as long as they remain equal, I can’t just do it in one operation because I can’t rely on the objects remaining equal.
That's not an optimization; what you've done is set arr1 to be a
reference to that object.
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any subsequent operations in arr1 will not affect mx1.
Yep, you have just set arr1 to be a completely different object.
So where I’m rewriting some Python code in a low level language, I can’t assume that the two objects are equal because that equality will not remain if either is reassigned. So if I do some operation on one array I have to conform the two
Is my understanding of this correct? Is there anything I’m missing? >>>>>
Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to think in
terms of object references the entire way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
There are cases where NumPy would be the best choice, but that wasn’t
the case here with what the loop was doing.
To sum up what I learned from this post, where one object derives from another object (a = b[0], for example), any operation that would alter
one will alter the other.
When either is assigned to something else,
then they no longer point to the same memory location and they’re once again independent.
I hope the word "derives" sidesteps the semantic
issue of whether they are "equal."
Thanks to all who replied to this post.
Jen
Jan 10, 2023, 13:59 by list1@tompassin.net:
Just to add a possibly picky detail to what others have said, Python
does not have an "array" type. It has a "list" type, as well as some
other, not necessarily mutable, sequence types.
If you want to speed up list and matrix operations, you might use
NumPy. Its arrays and matrices are heavily optimized for fast
processing and provide many useful operations on them. No use
calling out to C code yourself when NumPy has been refining that for
many years.
On 1/10/2023 4:10 PM, MRAB wrote:
On 2023-01-10 20:41, Jen Kris via Python-list wrote:
Thanks for your comments. I'd like to make one small
point. You say:
"Assignment in Python is a matter of object references. It's not
"conform them as long as they remain equal". You'll have to
think in
terms of object references the entire way."
But where they have been set to the same object, an
operation on one will affect the other as long as they are
equal (in Python). So I will have to conform them in those
cases because Python will reflect any math operation in both
the array and the matrix.
It's not a 2D matrix, it's a 1D list containing references to 1D
lists, each of which contains references to Python ints.
In CPython, references happen to be pointers, but that's just an
implementation detail.
Jan 10, 2023, 12:28 by rosuav@gmail.com:
On Wed, 11 Jan 2023 at 07:14, Jen Kris via Python-list
<python-list@python.org> wrote:
I am writing a spot speedup in assembly language for
a short but computation-intensive Python loop, and I
discovered something about Python array handling
that I would like to clarify.
For a simplified example, I created a matrix mx1 and
assigned the array arr1 to the third row of the matrix:
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
The pointers to these are now the same:
ida = id(mx1[2]) - 140260325306880
idb = id(arr1) - 140260325306880
That’s great because when I encounter this in
assembly or C, I can just borrow the pointer to row
3 for the array arr1, on the assumption that they
will continue to point to the same object. Then when
I do any math operations in arr1 it will be
reflected in both arrays because they are now
pointing to the same array:
That's not an optimization; what you've done is set arr1
to be a
reference to that object.
But on the next iteration we assign arr1 to
something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2], and any
subsequent operations in arr1 will not affect mx1.
Yep, you have just set arr1 to be a completely different
object.
So where I’m rewriting some Python code in a low
level language, I can’t assume that the two objects
are equal because that equality will not remain if
either is reassigned. So if I do some operation on
one array I have to conform the two arrays for as
long as they remain equal, I can’t just do it in one
operation because I can’t rely on the objects
remaining equal.
Is my understanding of this correct? Is there
anything I’m missing?
Assignment in Python is a matter of object references.
It's not
"conform them as long as they remain equal". You'll have
to think in
terms of object references the entire way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
I am writing a spot speedup in assembly language for a short but computation-intensive Python
loop, and I discovered something about Python array handling that I would like to clarify.
But on the next iteration we assign arr1 to something else:
arr1 = [ 10, 11, 12 ]
idc = id(arr1) – 140260325308160
idd = id(mx1[2]) – 140260325306880
Now arr1 is no longer equal to mx1[2]...
There are cases where NumPy would be the best choice, but that wasn’t the case here with what the loop was doing.memory location and they’re once again independent. I hope the word "derives" sidesteps the semantic issue of whether they are "equal."
To sum up what I learned from this post, where one object derives from another object (a = b[0], for example), any operation that would alter one will alter the other. When either is assigned to something else, then they no longer point to the same
On Wed, 11 Jan 2023 at 09:08, Thomas Passin <list1@tompassin.net> wrote:
Just to add a possibly picky detail to what others have said, Python
does not have an "array" type. It has a "list" type, as well as some
other, not necessarily mutable, sequence types.
Just to be even pickier, Python DOES have an array type, but it's not
the one the OP was using :)
https://docs.python.org/3/library/array.html
where one object derives from another object (a = b[0], for example), any operation that would alter one will alter the other.
On 11/01/23 11:21 am, Jen Kris wrote:
where one object derives from another object (a = b[0], for example), any operation that would alter one will alter the other.
I think you're still confused. In C terms, after a = b[0], a and b[0]
are pointers to the same block of memory. If you change that block of
memory, then of course you will see the change through either pointer.
Here's a rough C translation of some of your Python code:
/* mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] */
int **mx1 = (int **)malloc(3 * sizeof(int *));
mx1[0] = (int *)malloc(3 * sizeof(int));
mx1[0][0] = 1;
mx1[0][1] = 2;
mx1[0][2] = 3;
mx1[1] = (int *)malloc(3 * sizeof(int));
mx1[1][0] = 4;
mx1[1][1] = 5;
mx1[1][2] = 6;
mx1[2] = (int *)malloc(3 * sizeof(int));
mx1[2][0] = 7;
mx1[2][1] = 8;
mx1[2][2] = 9;
/* arr1 = mx1[2] */
int *arr1 = mx[2];
/* arr1 = [ 10, 11, 12 ] */
arr1 = (int *)malloc(3 * sizeof(int));
arr1[0] = 10;
arr1[1] = 11;
arr1[2] = 12;
Does that help your understanding?
--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Each name has the same pointer
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two objects,
Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.change will of course be visible through all of them.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
Just to add a possibly picky detail to what others have said, Python
does not have an "array" type. It has a "list" type, as well as some
other, not necessarily mutable, sequence types.
Thanks for your comments. After all, I asked for clarity so it’s not pedantic to be precise, and you’re helping to clarify.my example, but operations can be done in Python using either name.
Going back to my original post,
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
Now if I write "arr1[1] += 5" then both arr1 and mx1[2][1] will be changed because while they are different names, they are the assigned same memory location (pointer). Similarly, if I write "mx1[2][1] += 5" then again both names will be updated.
That’s what I meant by "an operation on one is an operation on the other." To be more precise, an operation on one name will be reflected in the other name. The difference is in the names, not the pointers. Each name has the same pointer in
Jan 11, 2023, 09:13 by roel@roelschroeven.net:objects, and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two
change will of course be visible through all of them.Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
Jen Kris <jenkris@tutanota.com> writes:
Each name has the same pointer
... from the C programmer's point of view.
From the Python programmer's point of view, there are no "pointers".
Instead, names or other targets are /assigned/ or /bound/ to objects.
|... the sequence is asked to assign the assigned object to
| its item with that index ...
|... the name is bound to the object ...
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two objects,
Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.change will of course be visible through all of them.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
As an example, you can create a named slice such as:
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet.
<avi.e.gross@gmail.com> writes:
As an example, you can create a named slice such as:From a functional programming point of view this just looks like a
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet.
partially applied function,
Jen,at least not the items you want to extract.
It is dangerous territory you are treading as there are times all or parts of objects are copied, or changed in place or the method you use to make a view is not doing quite what you want.
As an example, you can create a named slice such as:
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet. But given a long enough list or other such objects, it will take items (starting at index 0) starting with item that are at indices 5 then 7 then 9 as in this:
nums = [n for n in range(12)]
nums[middle_by_two]
[5, 7, 9]
The same slice will work on anything else:
list('abcdefghijklmnopqrstuvwxyz')[middle_by_two]
['f', 'h', 'j']
So although you may think the slice is bound to something, it is not. It is an object that only later is briefly connected to whatever you want to apply it to.
If I later change nums, above, like this:
nums = [-3, -2, -1] + nums
nums
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
nums[middle_by_two]
[2, 4, 6]
In the example, you can forget about whether we are talking about pointers directly or indirectly or variable names and so on. Your "view" remains valid ONLY as long as you do not change either the slice or the underlying object you are applying to --
Since my example inserted three new items at the start using negative numbers for illustration, you would need to adjust the slice by making a new slice designed to fit your new data. The example below created an adjusted slice that adds 3 to the startand stop settings of the previous slice while copying the step value and then it works on the elongated object:
middle_by_two_adj = slice(middle_by_two.start + 3, middle_by_two.stop + 3, middle_by_two.step)copy and make sure the only thing ever changing it is your code and later, if needed, copy the result back to any other data structure. Of course, if anything else is accessing the result in the original in between, it won't work.
nums[middle_by_two_adj]
[5, 7, 9]
A suggestion is that whenever you are not absolutely sure that the contents of some data structure might change without your participation, then don't depend on various kinds of aliases to keep the contents synchronized. Make a copy, perhaps a deep
Just FYI, a similar analysis applies to uses of the numpy and pandas and other modules if you get some kind of object holding indices to a series such as integers or Booleans and then later try using it after the number of items or rows or columns havechanged. Your indices no longer match.
Aviexample, but operations can be done in Python using either name.
-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Jen Kris via Python-list
Sent: Wednesday, January 11, 2023 1:29 PM
To: Roel Schroeven <roel@roelschroeven.net>
Cc: python-list@python.org
Subject: Re: To clarify how Python handles two equal objects
Thanks for your comments. After all, I asked for clarity so it’s not pedantic to be precise, and you’re helping to clarify.
Going back to my original post,
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
Now if I write "arr1[1] += 5" then both arr1 and mx1[2][1] will be changed because while they are different names, they are the assigned same memory location (pointer). Similarly, if I write "mx1[2][1] += 5" then again both names will be updated.
That’s what I meant by "an operation on one is an operation on the other." To be more precise, an operation on one name will be reflected in the other name. The difference is in the names, not the pointers. Each name has the same pointer in my
Jan 11, 2023, 09:13 by roel@roelschroeven.net:objects, and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two
change will of course be visible through all of them.Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
Avi,
Thanks for your comments. You make a good point.
Going back to my original question, and using your slice() example:
middle_by_two = slice(5, 10, 2)
nums = [n for n in range(12)]
q = nums[middle_by_two]
x = id(q)
b = q
y = id(b)
If I assign "b" to "q", then x and y match – they point to the same memory until "b" OR "q" are reassigned to something else. If "q" changes during the lifetime of "b" then it’s not safe to use the pointer to "q" for "b", as in:
nums = [n for n in range(2, 14)]
q = nums[middle_by_two]
x = id(q)
y = id(b)
Now "x" and "y" are different, as we would expect. So when writing a spot speed up in a compiled language, you can see in the Python source if either is reassigned, so you’ll know how to handle it. The motivation behind my question was that in a compiled extension it’s faster to borrow a pointer than to move an entire array if it’s possible, but special care must be taken.
Jen
Jan 12, 2023, 20:51 by avi.e.gross@gmail.com:
Jen,
It is dangerous territory you are treading as there are times all orparts of objects are copied, or changed in place or the method you use to make a view is not doing quite what you want.
As an example, you can create a named slice such as:
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet. But given a longenough list or other such objects, it will take items (starting at index 0) starting with item that are at indices 5 then 7 then 9 as in this:
nums = [n for n in range(12)]
nums[middle_by_two]
[5, 7, 9]
The same slice will work on anything else:
list('abcdefghijklmnopqrstuvwxyz')[middle_by_two]
['f', 'h', 'j']
So although you may think the slice is bound to something, it is not. Itis an object that only later is briefly connected to whatever you want to apply it to.
If I later change nums, above, like this:
nums = [-3, -2, -1] + nums
nums
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
nums[middle_by_two]
[2, 4, 6]
In the example, you can forget about whether we are talking aboutpointers directly or indirectly or variable names and so on. Your "view" remains valid ONLY as long as you do not change either the slice or the underlying object you are applying to -- at least not the items you want to extract.
Since my example inserted three new items at the start using negativenumbers for illustration, you would need to adjust the slice by making a
new slice designed to fit your new data. The example below created an adjusted slice that adds 3 to the start and stop settings of the previous slice while copying the step value and then it works on the elongated
object:
middle_by_two_adj = slice(middle_by_two.start + 3, middle_by_two.stop +3, middle_by_two.step)
nums[middle_by_two_adj]
[5, 7, 9]
A suggestion is that whenever you are not absolutely sure that thecontents of some data structure might change without your participation,
then don't depend on various kinds of aliases to keep the contents synchronized. Make a copy, perhaps a deep copy and make sure the only
thing ever changing it is your code and later, if needed, copy the result back to any other data structure. Of course, if anything else is accessing the result in the original in between, it won't work.
Just FYI, a similar analysis applies to uses of the numpy and pandas andother modules if you get some kind of object holding indices to a series
such as integers or Booleans and then later try using it after the number
of items or rows or columns have changed. Your indices no longer match.
Avi
-----Original Message-----On Behalf Of Jen Kris via Python-list
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org>
Sent: Wednesday, January 11, 2023 1:29 PM
To: Roel Schroeven <roel@roelschroeven.net>
Cc: python-list@python.org
Subject: Re: To clarify how Python handles two equal objects
Thanks for your comments. After all, I asked for clarity so it’s notpedantic to be precise, and you’re helping to clarify.
Going back to my original post,
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
Now if I write "arr1[1] += 5" then both arr1 and mx1[2][1] will bechanged because while they are different names, they are the assigned same memory location (pointer). Similarly, if I write "mx1[2][1] += 5" then
again both names will be updated.
That’s what I meant by "an operation on one is an operation on theother." To be more precise, an operation on one name will be reflected in the other name. The difference is in the names, not the pointers. Each name has the same pointer in my example, but operations can be done in
Python using either name.
Jan 11, 2023, 09:13 by roel@roelschroeven.net:
operation on the other" make it sound like there are two operations.Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two objects, and "an operation on one" and "an
simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.Sometimes it doesn't matter if we're a bit sloppy for sake of
names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different
So, to be precise: there is only one object, with possible multiple
names refer to the same object, that change will of course be visible
through all of them.
loop variables, function arguments.Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...),
track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
The correct mental model is important here, and I do think you're on
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
Falsea=1234
b=1234
a is b
Not sure what happens if you manipulate the data referenced by 'b'
It seems to me that the the entire concept of relying on python's idea of where an object is stored is just plain dangerous. A most simple example might be:
>>> a=1
>>> b=1
>>> a is b
True
>>> a=1234
>>> b=1234
>>> a is b
False
Not sure what happens if you manipulate the data referenced by 'b' in the first example thinking you are changing something referred to by 'a' ... but you might be smart to NOT think that you know.
On Fri, Jan 13, 2023 at 9:00 AM Jen Kris via Python-list <> python-list@python.org> > wrote:a compiled extension it’s faster to borrow a pointer than to move an entire array if it’s possible, but special care must be taken.
Avi,
Thanks for your comments. You make a good point.
Going back to my original question, and using your slice() example:
middle_by_two = slice(5, 10, 2)
nums = [n for n in range(12)]
q = nums[middle_by_two]
x = id(q)
b = q
y = id(b)
If I assign "b" to "q", then x and y match – they point to the same memory until "b" OR "q" are reassigned to something else. If "q" changes during the lifetime of "b" then it’s not safe to use the pointer to "q" for "b", as in:
nums = [n for n in range(2, 14)]
q = nums[middle_by_two]
x = id(q)
y = id(b)
Now "x" and "y" are different, as we would expect. So when writing a spot speed up in a compiled language, you can see in the Python source if either is reassigned, so you’ll know how to handle it. The motivation behind my question was that in
-- at least not the items you want to extract.
Jen
Jan 12, 2023, 20:51 by >> avi.e.gross@gmail.com>> :
Jen,
It is dangerous territory you are treading as there are times all or parts of objects are copied, or changed in place or the method you use to make a view is not doing quite what you want.
As an example, you can create a named slice such as:
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet. But given a long enough list or other such objects, it will take items (starting at index 0) starting with item that are at indices 5 then 7 then 9 as in this:
nums = [n for n in range(12)]
nums[middle_by_two]
[5, 7, 9]
The same slice will work on anything else:
list('abcdefghijklmnopqrstuvwxyz')[middle_by_two]
['f', 'h', 'j']
So although you may think the slice is bound to something, it is not. It is an object that only later is briefly connected to whatever you want to apply it to.
If I later change nums, above, like this:
nums = [-3, -2, -1] + nums
nums
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
nums[middle_by_two]
[2, 4, 6]
In the example, you can forget about whether we are talking about pointers directly or indirectly or variable names and so on. Your "view" remains valid ONLY as long as you do not change either the slice or the underlying object you are applying to
start and stop settings of the previous slice while copying the step value and then it works on the elongated object:
Since my example inserted three new items at the start using negative numbers for illustration, you would need to adjust the slice by making a new slice designed to fit your new data. The example below created an adjusted slice that adds 3 to the
deep copy and make sure the only thing ever changing it is your code and later, if needed, copy the result back to any other data structure. Of course, if anything else is accessing the result in the original in between, it won't work.
middle_by_two_adj = slice(middle_by_two.start + 3, middle_by_two.stop + 3, middle_by_two.step)
nums[middle_by_two_adj]
[5, 7, 9]
A suggestion is that whenever you are not absolutely sure that the contents of some data structure might change without your participation, then don't depend on various kinds of aliases to keep the contents synchronized. Make a copy, perhaps a
have changed. Your indices no longer match.
Just FYI, a similar analysis applies to uses of the numpy and pandas and other modules if you get some kind of object holding indices to a series such as integers or Booleans and then later try using it after the number of items or rows or columns
in my example, but operations can be done in Python using either name.
Avi
-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=>> gmail.com@python.org>> > On Behalf Of Jen Kris via Python-list
Sent: Wednesday, January 11, 2023 1:29 PM
To: Roel Schroeven <>> roel@roelschroeven.net>> >
Cc: >> python-list@python.org
Subject: Re: To clarify how Python handles two equal objects
Thanks for your comments. After all, I asked for clarity so it’s not pedantic to be precise, and you’re helping to clarify.
Going back to my original post,
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
Now if I write "arr1[1] += 5" then both arr1 and mx1[2][1] will be changed because while they are different names, they are the assigned same memory location (pointer). Similarly, if I write "mx1[2][1] += 5" then again both names will be updated.
That’s what I meant by "an operation on one is an operation on the other." To be more precise, an operation on one name will be reflected in the other name. The difference is in the names, not the pointers. Each name has the same pointer
objects, and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Jan 11, 2023, 09:13 by >> roel@roelschroeven.net>> :
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two
that change will of course be visible through all of them.Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object,
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
--
**** Listen to my FREE CD at > http://www.mellowood.ca/music/cedars> **** Bob van der Poel ** Wynndel, British Columbia, CANADA **
EMAIL: > bob@mellowood.ca
WWW: > http://www.mellowood.ca
Thanks for your comments. You make a good point.
Going back to my original question, and using your slice() example:
middle_by_two = slice(5, 10, 2)
nums = [n for n in range(12)]
q = nums[middle_by_two]
x = id(q)
b = q
y = id(b)
If I assign "b" to "q",
then x and y match – they point to the same memory until "b" OR "q"
are reassigned to something else.
If "q" changes during the lifetime of "b" then it’s not safe to use
the pointer to "q" for "b", as in:
nums = [n for n in range(2, 14)]
q = nums[middle_by_two]
x = id(q)
y = id(b)
Now "x" and "y" are different, as we would expect.
So when writing a spot speed up in a compiled language,
The motivation behind my question was that in a compiled extension
it’s faster to borrow a pointer than to move an entire array if it’s possible, but special care must be taken.
As an example, you can create a named slice such as:
middle_by_two = slice(5, 10, 2)
The above is not in any sense pointing at anything yet.
From a functional programming point of view this just looks like a partially applied function, and with this in mind the behaviour to me seems to be completely as expected. No surprises here, or do I miss something?
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two objects,
Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.change will of course be visible through all of them.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
The situation I described in my original post is limited to a case such as x = y ... the assignment can be done simply by "x" taking the pointer to "y" rather than moving all the data from "y" into the memory buffer for "x"
Jen,few features.
This may not be on target but I was wondering about your needs in this category. Are all your data in a form where all in a cluster are the same object type, such as floating point?
Python has features designed to allow you to get multiple views on such objects such as memoryview that can be used to say see an array as a matrix of n rows by m columns, or m x n, or any other combo. And of course the fuller numpy package has quite a
However, as you note, there is no guarantee that any reference to the data may not shift away from it unless you build fairly convoluted logic or data structures such as having an object that arranges to do something when you try to remove it, such astinkering with the __del__ method as well as whatever method is used to try to set it to a new value. I guess that might make sense for something like asynchronous programming including when setting locks so multiple things cannot overlap when being done.
Anyway, some of the packages like numpy are optimized in many ways but if you want to pass a subset of sorts to make processing faster, I suspect you could do things like pass a memoryview but it might not be faster than what you build albeit probablymore reliable and portable.
I note another odd idea that others may have mentioned, with caution.
If you load the sys module, you can CAREFULLY use code like this.
a="Something Unique"
sys.getrefcount(a)
2
Note if a==1 you will get some huge number of references and this is meaningless. The 2 above is because asking about how many references also references it.
So save what ever number you have and see what happens when you make a second reference or a third, and what happens if you delete or alter a reference:
a="Something Unique"
sys.getrefcount(a)
2
b = a
sys.getrefcount(a)
3
sys.getrefcount(b)
3
c = b
d = a
sys.getrefcount(a)
5
sys.getrefcount(d)
5
del(a)
sys.getrefcount(d)
4
b = "something else"
sys.getrefcount(d)
3
So, in theory, you could carefully write your code to CHECK the reference count had not changed but there remain edge cases where a removed reference is replaced by yet another new reference and you would have no idea.
Avi
-----Original Message-----example, but operations can be done in Python using either name.
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Jen Kris via Python-list
Sent: Wednesday, January 11, 2023 1:29 PM
To: Roel Schroeven <roel@roelschroeven.net>
Cc: python-list@python.org
Subject: Re: To clarify how Python handles two equal objects
Thanks for your comments. After all, I asked for clarity so it’s not pedantic to be precise, and you’re helping to clarify.
Going back to my original post,
mx1 = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
arr1 = mx1[2]
Now if I write "arr1[1] += 5" then both arr1 and mx1[2][1] will be changed because while they are different names, they are the assigned same memory location (pointer). Similarly, if I write "mx1[2][1] += 5" then again both names will be updated.
That’s what I meant by "an operation on one is an operation on the other." To be more precise, an operation on one name will be reflected in the other name. The difference is in the names, not the pointers. Each name has the same pointer in my
Jan 11, 2023, 09:13 by roel@roelschroeven.net:objects, and "an operation on one" and "an operation on the other" make it sound like there are two operations.
Op 11/01/2023 om 16:33 schreef Jen Kris via Python-list:
Yes, I did understand that. In your example, "a" and "b" are the same pointer, so an operation on one is an operation on the other (because they’re the same memory block).
Sorry if you feel I'm being overly pedantic, but your explanation "an operation on one is an operation on the other (because they’re the same memory block)" still feels a bit misguided. "One" and "other" still make it sound like there are two
change will of course be visible through all of them.Sometimes it doesn't matter if we're a bit sloppy for sake of simplicity or convenience, sometimes we really need to be precise. I think this is a case where we need to be precise.
So, to be precise: there is only one object, with possible multiple names to it. We can change the object, using one of the names. That is one and only one operation on one and only one object. Since the different names refer to the same object, that
Note that 'name' in that sentence doesn't just refer to variables (mx1, arr1, ...) but also things like indexed lists (mx1[0], mx1[[0][0], ...), loop variables, function arguments.
The correct mental model is important here, and I do think you're on track or very close to it, but the way you phrase things does give me that nagging feeling that you still might be just a bit off.
--
"Peace cannot be kept by force. It can only be achieved through understanding."
-- Albert Einstein
--
https://mail.python.org/mailman/listinfo/python-list
--
https://mail.python.org/mailman/listinfo/python-list
Yes, in fact I asked my original question – "I discovered something about Python array handling that I would like to clarify" -- because I saw that Python did it that way.
On Sun, 15 Jan 2023 at 10:32, Jen Kris via Python-list <python-list@python.org> wrote:
The situation I described in my original post is limited to a case such as x = y ... the assignment can be done simply by "x" taking the pointer to "y" rather than moving all the data from "y" into the memory buffer for "x"
It's not simply whether it *can* be done. It, in fact, *MUST* be done
that way. The ONLY meaning of "x = y" is that you now have a name "x"
which refers to whatever object is currently found under the name "y".
This is not an optimization, it is a fundamental of Python's object
model. This is true regardless of what kind of object this is; every
object must behave this way.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
On Sun, 15 Jan 2023 at 11:38, Jen Kris <jenkris@tutanota.com> wrote:
Yes, in fact I asked my original question – "I discovered something about Python array handling that I would like to clarify" -- because I saw that Python did it that way.
Yep. This is not specific to arrays; it is true of all Python objects.Indeen, I also still have the impression that Jen is thinking in terms
Also, I suspect you're still thinking about things backwards, and am
trying to lead you to a completely different way of thinking that
actually does align with Python's object model.
Chris Angelico schreef op 15/01/2023 om 1:41:
On Sun, 15 Jan 2023 at 11:38, Jen Kris <jenkris@tutanota.com> wrote:Indeen, I also still have the impression that Jen is thinking in terms
about Python array handling that I would like to clarify" -- because I
Yes, in fact I asked my original question – "I discovered something
saw that Python did it that way.
Yep. This is not specific to arrays; it is true of all Python objects.
Also, I suspect you're still thinking about things backwards, and am
trying to lead you to a completely different way of thinking that
actually does align with Python's object model.
of variables that are possible aliased such as you can have in a
language like C, instead of objects with one or more names like we have
in Python. Jens, in the Python model you really have to think of the
objects largely independently of the names that are or are not
referencing the objects.
Avi,issue.
Your comments go farther afield than my original question, but you made some interesting additional points. For example, I sometimes work with the C API and sys.getrefcount may be helpful in deciding when to INCREF and DECREF. But that’s another
The situation I described in my original post is limited to a case such as x = y where both "x" and "y" are arrays – whether they are lists in Python, or from the array module – and the question in a compiled C extension is whether the assignmentcan be done simply by "x" taking the pointer to "y" rather than moving all the data from "y" into the memory buffer for "x" which, for a wide array, would be much more time consuming than just moving a pointer. The other advantage to doing it that way
The answers I got from this post confirmed that it I can use the pointer if "y" is not re-defined to something else during the lifespan of "x." If it is then "x" has to be restored to its original pointer. I did it that way, and helpfully thecompiler did not overrule me.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 72:38:04 |
Calls: | 6,714 |
Calls today: | 2 |
Files: | 12,246 |
Messages: | 5,357,083 |