Is it possible to link dictionary values with list items?

I hope I can explain my question because my knowledge English is limited.
This is not blender specific question but I couldn’t find any useful Python forums to ask this.
Is it possible to create dictionary with values that are linked to some list items and if it is, how it can be done?
For instance, I have dictionary myDict and I want to link it’s values with items from list myList. When I change item in myList, belonging value in myDict should also be changed.

it depends what the item is - if its a list or blender data (vert, object, face, scene etc), then yes.
if its an int/float/string or tuple then no.
sometimes I put items in a single list just so this is possible which makes me want pointers in python :slight_smile:

Actually I suspected that answer… But I’ve had to ask :smiley:
Wouldn’t be nice to have something like this in Python:


>>a = 1
>>b = @a  #or something like that
>>print a, b
1 1
>> b = 2
>> print a, b
2 2
>> a = 3
>> print a, b
3 3

an alternate syntax would be nicer.

a, b = 1,2

*a = 3

print b

>> 3

But pythoners will tell you of the importance of immutableness

Well, we could have a nice debate about nicer syntax of non existing pointers in Python :smiley: You’re probably right about what they would say, but to me that’s absurd :no: Let’s imagine that’s one day Linus says “Immutableness is important so let’s remove symlinks and hardinks from Linux file systems”

Perhaps it would make sense to use a dummy object as a workaround?


class Dummy():
    pass

a = Dummy()
b = a
a.val = 5
print a.val, b.val # should give 5 5
b.val = 10
print a.val, b.val # should give 10 10

This is linked to the distinction between mutable and immutable objects and to the referenced based assignment system.

Like pointers in other languages, if you change where a pointer is pointing, it doesn’t change all other pointers pointing to the same value. Using a double indirection (like BeBraw suggested) is the way to do it.

Martin

This looks flexible enough for my needs but I’ll see is it applicable in what I’m doing right now, thanks for the hint.

I learned Python coming from a C++ background, and this was one of the things that puzzled me most. It helped when I realized that there is no real assignment operator in Python, “=” only makes a variable point to something else. If you really want to assign something, init is your friend:

Python 2.5.1 (r251:54863, Mar 7 2008, 04:10:12)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>> l = [1,2,3]
>>> ll = l
>>> l.init([4,5,6])
>>> ll
[4, 5, 6]

This will only work for mutable types. As others have pointed out, there is no way to assign to immutables (ints,floats,strings,tuples).

I don’t get the example because:

a,b = 1,2

Is a valid python statment that assigns 1 to a and 2 to b, so the rest of the example didn’t make any sense to me.

It seems to me like you shouldn’t be relying on changing something in one context magically causeing something in another context in the first place if you can help it – unless that something is part of a known shared object thing, anyway.

For the given example, why not make the list a list of dict keys, then just do this

 thedict[mylist[i]] = something

instead? It’s one more access, but a hash lookup isn’t exactly expensive in python. Also, if you need to do a lot of accesses to one element in a row, this kind of code is your friend:

for item, key = (thedict[key], key for key in mylist): 
  item = smash(item).bang(anotheritem)
  item += green
  item = rotoscope(item, purple, flannel)
  item = page4(item)
  thedict[key] = item

… I’m not 100% sure I got the tuple parts of that generator right, i’m sure “for item in (thedict[key] for key in mylist)” would work … :slight_smile:

You could also do

I[:] = [4,5,6]

since that will replace the ‘whole list’ slice with the elements of the given list. And it uses base syntax instead of calling a special method.

You’re not the only one :smiley: But I think that he has forgotten to put something in that “*a=3” line :slight_smile:
Anyhow, trick with dummy classes works like a charm :slight_smile: Thanks BeBraw!

No it doesn’t. It makes “a” point to “1”, which is not a value or constant but a genuine Python int object. This is one of the beauties of Python, try to pull a trick like ’
'.join(“line 1”, “line 2”) in C!

Lists are not hashable.

This is not valid Python code

Yes I agree with that, in the case of lists. The init solution can be used on all other mutable types.

Lists are not hashable.

The difference between mylist[i] and mydict[mylist[i]] is a hash lookup, right? That’s what I meant. Since he wants mylist[i] = x to in effect do mydict[somekey] = x, I suggested storing the dict keys in the list and just accessing the dict when you need to do something to it, which costs an extra lookup in trade for not needing to keep two copies in sync.

The rest of it, I’ll just say I’m a fool for trying to write something complex without access to an interpreter :slight_smile:

TypeError: join() takes exactly one argument (2 given)
:wink:

Martin

Aha, I knew I’d done this before. You have to make the left side of the generator a tuple explicitly, and the for loop can do an implicit unpack on it.

C:\Program Files\Python25>python
Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> mydict = {'a':1, 'b':2, 'c':3}
>>> mylist = mydict.keys()
>>>
>>> for key, item in ((genkey, mydict[genkey]) for genkey in mylist):
...     print "Key: %s, Item: %s" % (key, item)
...
Key: a, Item: 1
Key: c, Item: 3
Key: b, Item: 2
>>>

Theeth - I do that all the time. That’s one I usually fix before I finish muttering about it %_%.

Definatly the seat-of-your-pants, what-does-that-button-do kind of coder – might be part of why I loathe java, dunno.

Hehe, of course it must be:


 '
'.join(["line 1", "line 2"])

Like Star Weaver, I also keep doing that wrong, same for append()… IMO, one of the few warts in Python, which is for the rest wonderfully intuitive.