Python Forum
Compiler fault or some kind of weird referencing bug?
Thread Rating:
  • 1 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Compiler fault or some kind of weird referencing bug?
#1
So below is my Python code. I'm just messing around with what I was going to use as base for a new project. But after only 2 minutes of writing, I hit a wall. I've been trying various methods to fix it, but I have failed so far unfortunately. Any help at all would be appreciated. The program itself is meant to store the results and then let those be accessed afterwards. In other words, the first things printed should match the second things printed.

It should be easy to understand once you run the code I'm sure, as for the problem, maybe not so. I added extra comments to the code, although it is not my usual practice. Equally, variable names are somewhat poor as I just want to make things work properly first. I've been programming in more languages than I can count for over 8 years now. But I suppose my Python must be rusty.

# Imports
from pprint import pprint

data = []
results = []

# XOR each piece of data based on the value of 'x'
def xorEncrypt(data, x):    
    for i in range(0, len(data)):
        data[i] = data[i] ^ x
    return data

# Fill up the data list with 0 to 15 - 16 entres in total
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
for x in range(0, 16):
    data.append(x)

# XOR 'encrypt' using the value of 'i' and add the results to a list (called
# 'results'). Plus, print the result with each iteration.
for i in range(0, 10):    
    result = xorEncrypt(data, i)    
    print("Result:", result)
    results.append(result)
    

# Break-line and heading
print("------------------------------------------------------------------")
print("Final reuslts:")

# Pretty print the results
pprint(results)
A photo of the output on my machine. A friend also got the same result using a brand new installation of Python on a fresh machine.
picpaste. com/pics/1sBgcjGJ.1494201640.png - It wouldn't like me post an image link with my first post, so I've spaced out the URL.
Reply
#2
You only ever create two lists. On line 23, when you append(), you're always appending the same object. Python passes around object references, as you mentioned, if you want copies of objects you have to be explicit (otherwise lots of operations would be really inefficient). The idiom for a shallow copy would be to do
results.append(result[:])
on line 23.
Reply
#3
(May-08-2017, 12:43 AM)micseydel Wrote: You only ever create two lists. On line 23, when you append(), you're always appending the same object. Python passes around object references, as you mentioned, if you want copies of objects you have to be explicit (otherwise lots of operations would be really inefficient). The idiom for a shallow copy would be to do
results.append(result[:])
on line 23.

Thank you very much for the help. It worked perfectly :) But could you explain why that works exactly and how you found out that you needed to do that in the first place?
Reply
#4
It's just an oddity of how lists work, as one of the few data types that's mutable.  result and data are both labels referring to the same list, so changing one changes the other.  You append that list to results, and then mutate the list some more... which changes results since it's still the same list.

Slicing it result[:] forces a copy, which breaks all ties to data, so future changes don't effect result or results.  You can also call list() on it, or tuple() to make it very clear that you intend it to be immutable.

>>> x = list(range(5))
>>> x
[0, 1, 2, 3, 4]
>>> y = x
>>> x[1] = 100
>>> x
[0, 100, 2, 3, 4]
>>> y
[0, 100, 2, 3, 4]
>>> y = list(x)
>>> x[2] = 200
>>> x
[0, 100, 200, 3, 4]
>>> y
[0, 100, 2, 3, 4]
>>> y = tuple(x)
>>> x
[0, 100, 200, 3, 4]
>>> y
(0, 100, 200, 3, 4)
>>> x[3] = 300
>>> x
[0, 100, 200, 300, 4]
>>> y
(0, 100, 200, 3, 4)
Reply
#5
(May-08-2017, 03:52 PM)nilamo Wrote: It's just an oddity of how lists work, as one of the few data types that's mutable.
Python provides no way to make things immutable yourself (though you can jump through hoops to approximate it), so any user-created class (including third-party modules) has this behavior. I wouldn't call it an "oddity" since it really is fundamental.

Also note that list[:] creates a shallow copy; your list contains a bunch of references to objects, so if the objects are mutable then you could run into similar issues. There's a deepcopy function for the generic case, though [:] is a common idiom for lists.
Reply
#6
(May-08-2017, 03:52 PM)nilamo Wrote: It's just an oddity of how lists work, as one of the few data types that's mutable.  
It's not an oddity - Python passes objects by reference (whoever comes form C/C++ background); assignment operator with an object on the right hand does not create a new object - it creates a new reference to an existing object (I wish someone has explained that to me a decade ago  Cry ).

Whoever is used to writing C++, knows to create a copy constructor for an assignment operation (wow, my memory still serves me well Dance ). list[:] may be interpreted as an equivalent of a shallow copy constructor.
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#7
(May-09-2017, 07:29 AM)volcano63 Wrote: I wish someone has explained that to me a decade ago Cry
didn't they? or you, finding it by yourself? I mean, I think that 'gotcha' is one of the first that bytes newcomers when start to work with lists...
Reply
#8
(May-09-2017, 07:35 AM)buran Wrote: didn't they? or you, finding it by yourself?
Quote:A long and windy road
Wall Resources were scarce a decade ago, and I was working mostly alone.

(May-09-2017, 07:35 AM)buran Wrote: I mean, I think that 'gotcha' is one of the first that bytes newcomers when start to work with lists...
bytes, I presume, programmers' Freudian Wink
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#9
Blush Ups, yeah, mistake :-)
Reply
#10
(May-08-2017, 12:43 AM)micseydel Wrote:
results.append(result[:])
on line 23.

After a second look at the code, I think the best solution to the specific issue will be to return a new encoded list - instead of changing the argument list in place (which is side-effect - considered bad practice?! )
def xorEncrypt(data, x):
   return [d ^ x for d in data]
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  When does Python need to use a compiler? JanOlvegg 5 2,997 Mar-09-2023, 04:24 PM
Last Post: snippsat
  What kind of list is this? jesse68 2 1,129 Jun-29-2022, 05:02 PM
Last Post: rob101
  make: *** [Makefile:29: all] Segmentation fault Anldra12 2 1,862 May-01-2022, 06:17 PM
Last Post: Anldra12
  name 'lblstatus' is not defined when referencing a label KatManDEW 4 1,506 Apr-21-2022, 12:33 PM
Last Post: KatManDEW
  Dictionary Referencing nickdavis2017 1 1,594 Nov-20-2021, 06:24 PM
Last Post: deanhystad
  Referencing string names in df to outside variables illmattic 1 1,357 Nov-16-2021, 12:47 PM
Last Post: jefsummers
  Segmentation fault (core dumped) hobbyist 1 10,463 Jun-07-2021, 12:56 PM
Last Post: supuflounder
  splitting lines, need to add element of same kind tester_V 6 3,105 Feb-20-2021, 11:51 PM
Last Post: tester_V
  What kind of object is this? Moris526 5 2,486 Dec-27-2020, 06:41 AM
Last Post: Gribouillis
  Referencing a fixed cell Mark17 2 2,049 Dec-17-2020, 07:14 PM
Last Post: Mark17

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020