3

I have a python dictionary that has the below format

data = {  'key1': 'value1',
  'key2': 'value2',
  'key3': 'value3'
}

I want this key3 value to point to the value of key1. what i tried so far is 'key3': key1['value1'] or 'key3': data['key1'] and both of them seem to be invalid syntaxes.

noob_coder
  • 749
  • 4
  • 15
  • 35
  • 1
    You can't reference the dictionary from within itself while constructing it as it doesn't exist as an object yet... – Jon Clements Mar 22 '19 at 05:05
  • Also - when you say *I want this key3 value to point to the value of key1* - did you expect when you changed the value of `key1` the accessing `key3` would give you the updated value or the old value? – Jon Clements Mar 22 '19 at 05:07
  • @JonClements i expect the value of `key3` to change when `key1` changes – noob_coder Mar 22 '19 at 05:10
  • Possible duplication :https://stackoverflow.com/questions/38254969/reference-a-dictionary-within-itself – Sean_Syue Mar 22 '19 at 05:10
  • Also - you'd need to be remarkably wary of cyclic references... if key3 should retrieve the value of key1's value, but accessing key1 tries to return the value of key3... – Jon Clements Mar 22 '19 at 05:19

2 Answers2

2

Python doesn't support pointers like C/C++ does, but you could use lists to serve as references. To access the value, you'd index into the first element of the list.

data = {
  'key1': ['value1']
}

data['key3'] = data['key1']     #  copy the list by reference
print(f"Old: {data['key3'][0]}, {data['key3'][0] == data['key1'][0]}")

data['key1'][0] = 'new-value'   #  this will modify the value from data['key3'] as well    
print(f"New: {data['key3'][0]}, {data['key3'][0] == data['key1'][0]}")

Output:

Old: value1, True
New: new-value, True

Note that, this assumes that you're fully aware of which values act as "pointers" and which ones don't.

For example,

data = {
  'key1': ['pointer-list'],    # should act as a "pointer"
  'key2': ['normal', 'list']   # should act as a normal list
}

data['key3'] = data['key1']    # copy list by reference
data['key1'][0] = 'new-value'  # propogate new value to other references

data['key4'] = data['key2']    # oops – copy list by reference
data['key2'][0] = 'new-value'  # oops – data['key2'] should act as a normal list but
                               # the new value is propogated to data['key4'] as well

To deal with this issue, clone or copy the list instead.

import copy
data['key4'] = copy.copy(data['key2'])

# data['key4'] = copy.deepcopy(data['key2']) # if the value contains nested lists
# data['key4'] = data['key2'].copy()   # another way
TrebledJ
  • 8,713
  • 7
  • 26
  • 48
  • You have to know to check if it's a list though... and then if lists are valid values, then... – Jon Clements Mar 22 '19 at 05:14
  • @JonClements As in... before the value is set (e.g. checking before `data['key1'][0] = 'new_value'`)? I don't quite understand the other part, can you elaborate a bit more? :D – TrebledJ Mar 22 '19 at 05:16
  • If I access `key1` directly... I have to *know* it's actual value is the string `value1` and it's *actual* value isn't really a 1-element list... eg: how do I know the difference between it's actually a single element list and not just a single element list because it's being shared? – Jon Clements Mar 22 '19 at 05:23
  • @JonClements Hmm... I was assuming that the OP will know which lists serve as "pointers" and which lists serve as "lists". If there's a dynamic spin to it... then I think your concern is entirely valid. – TrebledJ Mar 22 '19 at 05:32
  • 1
    A dynamic work around would be a custom dict-like object that only contains values that references another dict, and that dict contains the real values, eg: `{'key1': 1, 'key2': 2, 'key3': 1}` and that proxies all operations to the real dict such as `{1: 'value1', 2: 'value2'}`... – Jon Clements Mar 22 '19 at 05:38
  • 1
    I suppose another consideration is what should the behaviour of `del data['key1']` have... should `key3` be keeping that object alive or since the value of what *it held* is gone, should `key3` now not have a value? :) – Jon Clements Mar 22 '19 at 05:42
  • 1
    I suppose what you could do here is make *everything* a list and *always* make sure to access the first element... that way the ambiguity is gone. – Jon Clements Mar 22 '19 at 05:52
  • @Jon I'm tempted to say "These considerations are left as an exercise for the reader." :P Good points, nonetheless. – TrebledJ Mar 22 '19 at 06:06
1

Try this

data = { 'key1': 'value1', 'key2': 'value2', 'key3': 'value3' }

data['key3'] = data['key1']

print(data)

Prints out:

{'key3': 'value1', 'key2': 'value2', 'key1': 'value1'}
Leonid
  • 622
  • 3
  • 9
  • 22