[open] Global/local variables and lists
Greetings.
I'm a bit confused about the local/global variable stuff. At the moment, I'm coding three inline_scripts that create random lists, draw from one of them, and use the drawn item for another task, respectively. They are all part of the same trial sequence. In the first script, variables and lists are defined and set globally, and are then used in the two latter scripts.
Here's the first script:
import random
global list1, list2, random
list = [] # create empty list
# append five 1s and 2s to the list:
for i in range(5):
list.append(1)
list.append(2)
# define shuffle list function, which takes a list as its argument:
def shuffleList(list):
L = list[:] # copy the input list
random.shuffle(L) # and shuffle the copy
return L # return shuffled copy
# create 2 shuffled lists:
list1 = shuffleList(list)
list2 = shuffleList(list)
My questions are:
1) Am I correct in assuming, that I only need exp.set or exp.get if I wish to use these variables and lists in other items, outside this sequence?
2) How come I need to declare random global in order to use it in my shuffleList function?
Best regards,
Jákup
Comments
Hi Jákup,
Your questions go a lot deeper than you probably thought:
'normally', yes: for communication between multiple items (or the 'run' and 'prepare' phases for that matter) can best be done through exp.get() and exp.set(). However, in this thread Lotje mentioned how Opensesame treats list variables: as strings (they're not ints or floats). This is somewhat problematic if you wish to convert them back to their original types. E.g. In 0.26, I tested setting:
which crashed because OS attempted to evaluate '[1,2,3,4]' as one bracket-enclosed variable.
The solution would be to circumvent the get and set methods, by simply creating your variable in the exp object directly, e.g.
Some words of warning though:
variables set as such will not be logged by the logger
make sure your variable names do not overwrite critical OS fields: for example don't say exp.width = 15 because this overwrites OS's variable for the screen width.
As for your second question;
Internally, your script is not run as a python program. Rather, it is represented as one string, and then the functions inline_script.prepare() and inline_script.run() compile and execute this string by calling python's compile() and exec() functions.
This works -almost- the same, except for some limitations. Because you're running things from within a function (prepare() or run()), modules and variables are defined with only a local scope, i.e. defined within that function. If you now define another function within this function (i.e. your shuffleList function), python would usually transport these local variables and modules into the inner function.
However, with exec() this doesn't happen (here's a thread to get you started on why ). Local variables and modules are not passed onto the inner function, and therefore random is not defined in this function.
You can see this in a python terminal, using the locals() and globals() functions:
yields:
Whereas when running the same program as 'regular code'
runs fine, yielding:
...because as you can see, the 'locals' are transported into fun.
it's pretty technical, but I hope this clarifies matters a bit!
As for your program; if you don't want to type (shuffle) the whole time, you can always define a for-loop, right?
Hope this helps,
Wouter
Dear Wouter.

Thank you very much for your excellent explanation! This really cleared things up for me. You are right in saying, it ran deeper than I had imagined! I actually thought long about whether or not I should even post, as the questions seemed almost too simple.
And thanks for the 5x multiplication trick instead of appending. Another great example of how elegant Python can be
Best regards,
Jákup
Try this detailed tutorial on...python list