1

I want to use a dictionary representing a directed graph with a certain number of nodes (num) and with all possible edges (output).

Examples:

if num = 1, output: {0: set([])}

if num = 2, output: {0: set([1]), 1: set([0])}

if num = 3, output: {0: set([1,2]), 1: set([0,2]), 2: set([0,1])}

if num = 4, output: {0: set([1,2,3]), 1: set([0,2,3]), 2: set([0,1,3]), 3: set([0,1,2])}

My code will iterate through the dictionary and create each set by remove the key from a temperate list:

num = 3
keys = range(0,num)
mydict ={} 
for key in keys:
    temp = keys
    value_list = temp.remove(key)
    mydict[key] = set([value_list])

But it seemed by using temp.remove(key), not only temp but also keys would be muted. Why is that?

enaJ
  • 1,565
  • 5
  • 16
  • 29

1 Answers1

1

Most objects (not primitives like ints) you use in Python are just references to the actual data. What that means is that in your example, temp and keys are both pointers referencing the same data.

keys = range(0,num)                # Bind keys to a new list instance = [0, 1, 2, ..., num]
mydict = {} 
for key in keys:
    temp = keys                    # Bind temp to the same dictionary as keys
    value_list = temp.remove(key)  # Remove from the list temp and keys point to
    ...

If you want temp to point to a unique list, there are several ways to do it, but I prefer something like:

temp = list(keys)

EDIT: According to the analysis done here by cryo, this strange syntax is slightly faster (known as slicing)

temp = list[:]
Community
  • 1
  • 1
Curmudgeon
  • 194
  • 11
  • Glad to hear it! I'm not sure if you get notifications for this, but I edited my answer a bit. Turns out there's a slightly faster method for doing what you want to do. Good luck! – Curmudgeon Jun 12 '15 at 17:40
  • Thank you. I see the new updated syntax now. Also, I don't understand this "Most objects (not primitives like ints) you use in Python are just references to the actual data", though your solution help to overcome this problem. Could you please expand more on this front? – enaJ Jun 12 '15 at 19:59
  • 1
    Sure thing! Basically, since integers are single pieces of data, they can be stored at a single memory address. Arrays, on the other hand, need many memory addresses. Typically, for some more in-depth memory allocation reasons, that memory address holds _another address_ rather than a piece of data. That address points to the beginning of the actual array. For that reason, when you set temp = list, what you're actually doing is setting temp to the same pointer that list has, which points to the array itself. If that explanation was too compact/confusing, Googling "pointers" might help a bit :) – Curmudgeon Jun 13 '15 at 01:05
  • `A = [1,2] B = A B = [1,2,3] B.remove(1)` A will still be [1,2]. It doesn't seemed like list A will be changed. – enaJ Jun 13 '15 at 22:38
  • 1
    Correct, it won't be -- in that case B and A are pointing to the same location immediately after `B = A` but when you do `B = [1, 2, 3]` you create a new list and B _and only B_ is set to contain a pointer pointing at that list. – Curmudgeon Jun 14 '15 at 01:23