Python list indices must be int, not str

I need to use a string to assess a list of objects like you would with scene.objects[“ObjName”] now apparently I cant do that with a list, but it can be done with the scene.objects[].
The reason I need this is I want to be able to write Own.AI = list[own.PropertyAI] where PropertyAI is a string with the name of the AI that the object will use. This way a single script can assign AIs for all objects at once
Thank you in advance
p.s.:
scene.objects[] = GameLogic.getCurrentScene().objects[]
[own = GameLogic.getCurrentController().owner
PropertAI is assighned to the object in the logic buttons pannal

objects[]?
I never saw that syntax. I wonder what it does.

What is Own.AI = … ?
If Own is a KX_GameOBject this syntax is deprecated. Use own[“AI”] = … instead.

Anyway.

scene.object returns a CList. It is a hybrid of a list and a dict. (In my eyes not a very good hybrid as lists can have non-unique values)

I advice you to use a dictionary rather than a list.
As key you can use the string. As value you can use whatever you want (even a list or another dictionary).


own["ai"] = {"key": object, "otherKey":objectB }
 
# or 
 
own["otherAi"] = {}
own["otherAi"]["key"] = object
own["otherAi"].update({ "next": otherKey":objectB })

Keep in mind keys must be unique. If you set the same key again, the item will be overwritten.

I hope it helps

I do something similar, using a list of guns on a vehicle:

[["r_laser",6,0.5,1,90,0,5,0,0,0.5,0.17,"small laser"],["b_laser",2,4,1,450,0,3,0,0,5,4,"large laser"],["mg",8,0.25,2,90,0,5,0.06,0,0.5,0,"machinegun"]]

So to manipulate the third gun, the machine gun, I would use gun[2]
rather than gun[“machinegun” ] …

You have to use numbers, not names to find objects in a list.

I usually make a note of what each number means:

# [0]Bullet-type[1]rate[2]damage[3]damage_type[4]range[5]min_range[6]spread[7]ammo[8]reload[9]tons[10]heat[11]name

You could also split the list entries too, to make debugging easier:

gun = [["gun_1"],["r_laser",6,0.5,1,90,0,5,0,0,0.5,0.17,"small laser"]]

Then you use gun[0][1] to get the data, or gun[0][0] to get the label for debugging. Then for example gun[0][1][11] would return “small laser”

This lets you work with very flexible lists which can be stored in properties as strings.
Much better than working with very long lists of individual properties or multiple game objects.

A handy way of keeping track of a list of numbers is to create a class that acts like an enum in Python:


class stats:
    BULLET_TYPE = 0
    RATE = 1
    DAMAGE = 2
    DAMAGE_TYPE = 3
    #etc...

print(stats.BULLET_TYPE, stats.RATE, stats.DAMAGE_TYPE)

I find this makes my code easier to read and debug. You can also kind of use variable names to represent integers.

For accessing information with strings though, as Monster said, you need a dictionary.

I often find I have to send my data as an unformatted string using a network message in blender.
So I use my method of mixed lists.
They are easier to put together in to a raw string (adding “$” or “?” as a speperator between entries).
Then I can use the split function to break them back in to useable lists.

In such cases it would be better for performance not to send all the data as string. Because you need to convert to string and back.

What you can do is to store the data at a central location in a dictionary. Then send the key only. If each involved object knows the central location (e.g another object, scene, module, or GameLogic) they have fast access to the data.

If you want to send “one-time” data, you can generate a new key with each transmission. E.g. setup a message counter that increases with each message. The data could be removed after dealing with it.

This method does not work if you send messages to another application, but inside the same application.

OK, that sounds reasonable, I’ll try that for my next project.