Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Python中的“if-letter in-dict”工作错误?_Python_String_List_If Statement_List Comprehension - Fatal编程技术网

为什么Python中的“if-letter in-dict”工作错误?

为什么Python中的“if-letter in-dict”工作错误?,python,string,list,if-statement,list-comprehension,Python,String,List,If Statement,List Comprehension,我正在尝试编写一个函数,它返回一个字符串,该字符串中的字母不是LettersGuesed words = list('abcdefghijklmnopqrstuvwxyz') def getAvailableLetters(lettersGuessed): [words.remove(letter) for letter in words if letter in lettersGuessed] return ''.join([str(elem) for elem in wor

我正在尝试编写一个函数,它返回一个字符串,该字符串中的字母不是LettersGuesed

words = list('abcdefghijklmnopqrstuvwxyz')

def getAvailableLetters(lettersGuessed):
    [words.remove(letter) for letter in words if letter in lettersGuessed]
    return ''.join([str(elem) for elem in words]) 
然后我调用我的函数

getAvailableLetters(['e', 's', 'i', 'k', 'p', 'r'])
但结果与我预期的不同。 我的输出:

'abcdfghjlmnoqstuvwxyz' 

# the letter 's' in the output, but it shouldn't be there.
正确输出:

'abcdfghjlmnoqtuvwxyz' 

我做错了什么?

原因是您在遍历列表时正在修改列表-不应该这样做。 我将在这里分享@AlexMartelli给出的建议:

永远不要更改正在循环的容器,因为容器上的迭代器不会被通知您的更改,而且正如您所注意到的,这很可能会产生一个非常不同的循环和/或一个不正确的循环

这里有一个替代解决方案,也使用snake_case,使用集合——假设可用字母和猜测字母都不包含重复字母,除非是错误:

all_letters = set('abcdefghijklmnopqrstuvwxyz')

def get_available_letters(letters_guessed):
    available_letters = all_letters - set(letters_guessed)
    return ''.join([str(letter) for letter in available_letters])
这里有一个警告,上面的解决方案可能不遵守您指定字母的顺序

如果您仍想坚持列表,请分两个阶段进行:

all_letters = list('abcdefghijklmnopqrstuvwxyz')

def get_available_letters(letters_guessed):
    available_letters = [letter for letter in all_letters if letter not in letters_guessed]
    return ''.join([str(letter) for letter in available_letters])

原因是您在遍历列表时正在修改它-不应该这样做。 我将在这里分享@AlexMartelli给出的建议:

永远不要更改正在循环的容器,因为容器上的迭代器不会被通知您的更改,而且正如您所注意到的,这很可能会产生一个非常不同的循环和/或一个不正确的循环

这里有一个替代解决方案,也使用snake_case,使用集合——假设可用字母和猜测字母都不包含重复字母,除非是错误:

all_letters = set('abcdefghijklmnopqrstuvwxyz')

def get_available_letters(letters_guessed):
    available_letters = all_letters - set(letters_guessed)
    return ''.join([str(letter) for letter in available_letters])
这里有一个警告,上面的解决方案可能不遵守您指定字母的顺序

如果您仍想坚持列表,请分两个阶段进行:

all_letters = list('abcdefghijklmnopqrstuvwxyz')

def get_available_letters(letters_guessed):
    available_letters = [letter for letter in all_letters if letter not in letters_guessed]
    return ''.join([str(letter) for letter in available_letters])

我将给您一个小示例,以了解在迭代时从列表中删除元素时发生的情况:

l = ['a', 'b', 'c', 'd', 'e', 'f']
for i, c in enumerate(l):
    print('_' * 25)
    print('iteration', i)
    print('index value', i)
    print('elemnt at index ', i, ':', l[i])
    print('list length:', len(l))
    l.remove(c)
    print('\nafter removing an element')
    print('list length:', len(l))

    print('index value', i)
    if len(l) > i:
        print('elemnt at index ', i, ':', l[i]) # this element will not be removed

print('_' * 40)
print('list after iterateion:', l)\
输出:

_________________________
iteration 0
index value 0
elemnt at index  0 : a
list length: 6

after removing an element
list length: 5
index value 0
elemnt at index  0 : b
_________________________
iteration 1
index value 1
elemnt at index  1 : c
list length: 5

after removing an element
list length: 4
index value 1
elemnt at index  1 : d
_________________________
iteration 2
index value 2
elemnt at index  2 : e
list length: 4

after removing an element
list length: 3
index value 2
elemnt at index  2 : f
________________________________________
list after iterateion: ['b', 'd', 'f']
如您所见,如果在迭代列表时删除一个元素,则会修改列表的大小,并且从一个迭代到另一个迭代,则会跳过下一个元素,for循环在每次迭代后都会随着索引的增加而增加,希望抓住下一个元素,但您会使用一个元素来收缩列表,因此for循环实际上会跳过1个元素

如果要修改全局变量字,可以使用:

def getAvailableLetters(lettersGuessed):
    global words
    words = [c for c in words if c not in lettersGuessed]

    return ''.join([str(elem) for elem in words])

getAvailableLetters(['e', 's', 'i', 'k', 'p', 'r'])
输出:

_________________________
iteration 0
index value 0
elemnt at index  0 : a
list length: 6

after removing an element
list length: 5
index value 0
elemnt at index  0 : b
_________________________
iteration 1
index value 1
elemnt at index  1 : c
list length: 5

after removing an element
list length: 4
index value 1
elemnt at index  1 : d
_________________________
iteration 2
index value 2
elemnt at index  2 : e
list length: 4

after removing an element
list length: 3
index value 2
elemnt at index  2 : f
________________________________________
list after iterateion: ['b', 'd', 'f']
如果只想返回不在LettersGuesed中的字母,而不修改全局变量字:


我将给您一个小示例,以了解在迭代时从列表中删除元素时发生的情况:

l = ['a', 'b', 'c', 'd', 'e', 'f']
for i, c in enumerate(l):
    print('_' * 25)
    print('iteration', i)
    print('index value', i)
    print('elemnt at index ', i, ':', l[i])
    print('list length:', len(l))
    l.remove(c)
    print('\nafter removing an element')
    print('list length:', len(l))

    print('index value', i)
    if len(l) > i:
        print('elemnt at index ', i, ':', l[i]) # this element will not be removed

print('_' * 40)
print('list after iterateion:', l)\
输出:

_________________________
iteration 0
index value 0
elemnt at index  0 : a
list length: 6

after removing an element
list length: 5
index value 0
elemnt at index  0 : b
_________________________
iteration 1
index value 1
elemnt at index  1 : c
list length: 5

after removing an element
list length: 4
index value 1
elemnt at index  1 : d
_________________________
iteration 2
index value 2
elemnt at index  2 : e
list length: 4

after removing an element
list length: 3
index value 2
elemnt at index  2 : f
________________________________________
list after iterateion: ['b', 'd', 'f']
如您所见,如果在迭代列表时删除一个元素,则会修改列表的大小,并且从一个迭代到另一个迭代,则会跳过下一个元素,for循环在每次迭代后都会随着索引的增加而增加,希望抓住下一个元素,但您会使用一个元素来收缩列表,因此for循环实际上会跳过1个元素

如果要修改全局变量字,可以使用:

def getAvailableLetters(lettersGuessed):
    global words
    words = [c for c in words if c not in lettersGuessed]

    return ''.join([str(elem) for elem in words])

getAvailableLetters(['e', 's', 'i', 'k', 'p', 'r'])
输出:

_________________________
iteration 0
index value 0
elemnt at index  0 : a
list length: 6

after removing an element
list length: 5
index value 0
elemnt at index  0 : b
_________________________
iteration 1
index value 1
elemnt at index  1 : c
list length: 5

after removing an element
list length: 4
index value 1
elemnt at index  1 : d
_________________________
iteration 2
index value 2
elemnt at index  2 : e
list length: 4

after removing an element
list length: 3
index value 2
elemnt at index  2 : f
________________________________________
list after iterateion: ['b', 'd', 'f']
如果只想返回不在LettersGuesed中的字母,而不修改全局变量字:

remove函数减少单词的长度,而在Python中,循环变量仅在循环开始时针对其限制进行初始化。试着用一个小例子来理解这一点

lis = [1, 2, 4, 6, 5]
for i in lis:
    if i % 2 == 0:
        lis.remove(i)
此代码输出[1,4,5],而预期输出为[1,5]。这是因为,我已经初始化为从0到5索引。第一次lis.remove删除2时,lis的长度减少了,它被更新为lis=[1,4,6,5],现在我应该指向下一个元素的4,而现在我指向6,即索引2,因为2位于索引1,因此从不检查值4。同样的情况也发生在代码中

对于解决方案,最好使用while循环。这个问题不会出现在while循环中,而只出现在for循环中。

remove函数会减少单词的长度,而在Python中,循环变量仅在循环开始时初始化其限制。试着用一个小例子来理解这一点

lis = [1, 2, 4, 6, 5]
for i in lis:
    if i % 2 == 0:
        lis.remove(i)
此代码输出[1,4,5],而预期输出为[1,5]。这是因为,我已经初始化为从0到5索引。第一次lis.remove删除2时,lis的长度减少了,它被更新为lis=[1,4,6,5],现在我应该指向下一个元素的4,而现在我指向6,即索引2,因为2位于索引1,因此从不检查值4。同样的情况也发生在代码中


对于解决方案,最好使用while循环。while循环不会出现此问题,但仅for循环会出现此问题。

迭代时不要删除元素。这将导致意外的行为。您可以迭代副本并删除元素。例如,单词中的字母[:]:words.removeletter。还有
re无需构建列表[单词中的字母的单词。移除字母[:]如果字母中的字母已被选中]。移除是一个就地操作,不会产生值。因此,实际上您正在构建一个无值列表。您在迭代列表的同时修改列表,这意味着您将跳过列表中的一些值。尝试类似于return.joinl的方法,如果l不在LettersGuesed中,则在单词中表示l,在迭代时不要删除元素。这将导致意外的行为。您可以迭代副本并删除元素。例如,单词中的字母[:]:words.removeletter。此外,也不需要构建列表[words.removeletter for letter in words[:]如果letter in letters被选中]。移除是一个就地操作,不会产生值。因此,实际上您正在构建一个无值列表。您在迭代列表的同时修改列表,这意味着您将跳过列表中的一些值。尝试一些类似return的方法。如果我不是用字母表示,那么用单词表示l