-1

我正在用 PsychoPy(一种用于使用 Python 进行心理学实验的软件)编写一个程序,并不断收到“列表索引超出范围”错误。问题出现在“if already_used_values[a] == value:”的行上。我可以看到为什么会发生这种情况的唯一可能原因是因为 already_used_values 开始时是一个空列表;但是,我认为如果列表为空,我通过说 return False 解决了这个问题。以下是相关代码供参考。

already_used_values = []#integers in order to sort sounds
sorted_sounds = []#note that these are not 'sorted', they are randomized each time
answer_key = []
def already_used(value):#returns true if value in array of sounds has been used
    if len(already_used_values) == 0:
        return False
    for a in already_used_values:
        if already_used_values[a] == value:
            return True
    return False
def pick_random_value(upLim):
    return random.randint(0,upLim-1)

def pick_sound(sound_list):#picks a sound randomly from list_of_sounds 
    new_value = pick_random_value(len(sound_list))
    while(already_used(new_value)):
        new_value = pick_random_value(len(sound_list))
    already_used_values.append(new_value)
    return sound_list[new_value]

def init_sorted_sounds():#appends random sound from list_of_sounds to sorted_sounds
    for i in list_of_sounds:
        sorted_sounds.append(pick_sound(list_of_sounds))
    answer_key = already_used_values

先感谢您!

4

1 回答 1

5

This pair of lines:

for a in already_used_values:
    if already_used_values[a] == value:

is the root of the error you report. When you say for a in something, the variable a takes on each value of the elements of something, not each index. Yet, in the next line, you're using a as an index. So for example if already_used_values is equal to [ 5, 6 ], on the first iteration a takes the value 5 and the subsequent line tries to examine already_used_values[ 5 ] which is clearly out of range of a 2-element list.

It's hard to tell the intention exactly, but it looks like your function already_used can be reduced to the single boolean-valued expression new_value in already_used_values

So the line

while(already_used(new_value)):

becomes

while( new_value in already_used_values ):

and we get rid of the function. But let's go one step further and recognize that, instead of the trial-and-error while loop you currently have, you can take a random pick of elements from a pool that already excludes used values before you perform the pick:

remaining_choices = [ x for x in sound_list if x not in already_used_values ]
new_value = random.choice( remaining_choices  )
already_used_values.append( new_value )

So that's got rid of the while loop. But we can even optimize one step further as pointed out by chthonicdaemon below. It looks like, in the end, what you're aiming to do with all this code is simply to find a random reordering of a list. This can be done in one or two lines:

sorted_sounds = list( list_of_sounds )  # make a copy of the original list of sounds
random.shuffle( sorted_sounds )  # randomly reorder the new list in place
于 2015-01-26T04:04:39.240 回答