Ошибка типа при проверке условия, связанного с функцией any() в Python

#python #generator

#python #генератор

Вопрос:

Первый вопрос по StackExchange… Я изучаю Python для выполнения некоторого анализа текста в течение нескольких месяцев, запустив Python 3.5 на Mac, и у меня возникла проблема с некоторым кодом, который выглядит следующим образом:

 from Levenshtein import distance
keywords = ['some', 'list']
line = 'some long string.'

for w in line.split():

    if condition_1 and not any(distance(w, k) < 2 for k in keywords):
        do_something

    elif condition_1 and any(distance(w, k) < 2 for k in keywords):
        do_something_else

    elif condition_2 and not any(distance(w, k) < 2 for k in keywords):
        do_a_third_thing

    else:
        do_somthing_completely_different
  

Когда цикл запускается, condition_1 и condition_2 являются False , поэтому я бы ожидал, что первая итерация цикла перейдет к четвертому варианту и сделает это. Но вместо этого, когда он проверяет третий случай, он выдает следующее сообщение об ошибке:

 TypeError: distance expected two Strings or two Unicodes
  

Если я перейду к этой строке в отладчике и проверю тип w и элементы keywords списка, они все str . Если я попытаюсь просто запустить проблемную команду в отладчике, я получу NameError:

 (Pdb) any(distance(w, k) < 2 for k in keywords)
*** NameError: name 'w' is not defined
  

Если вместо этого я введу литерал, присвоенный w , все в порядке:

 (Pdb) any(distance('some', k) < 2 for k in keywords)
True
  

Что заставляет меня думать, что это как-то связано с тем, как функция generator обрабатывает пространства имен, но я не уверен. Я попытался заменить встроенную функцию на distance(w, k) , например len(w k) , просто для проверки, и я получаю тот же набор ошибок. Я нахожу ошибку особенно запутанной, поскольку, похоже, нет проблем с проверкой первых двух случаев.

Я мог бы предложить обходной путь, но я хотел бы знать, что здесь на самом деле происходит. Google и StackExchange пока не принесли мне радости по этой теме. Любые мысли или предложения будут приняты с благодарностью.

Ответ №1:

вы могли бы сделать это намного проще, переформатировав свои операторы if внутри цикла и проверив тип W следующим образом:

 print(" W contains '{}' and is a {} ".format(w, type(w)))
assert w,str

if condition_1:
    result = any(distance(w, k) < 2 for k in keywords):
    print(" Result contains '{}' and is a {} ".format(result,type(result)  

    if result:    
        do_something
    else:
        do_something_else

elif condition_2:
    if not any(distance(w,k) < 2 for k in keywords):
        do_a_third_thing

else:
     do_something_completely_different
  

Я предполагаю, что вы получаете эти ошибки, работающие с другой строкой, чем в примере. Вы проверили, что оно действительно имеет значение, прежде чем разделить его?

Комментарии:

1. Да, строка в моем коде намного длиннее, чем в примере, который я привел. Я проверил, что у нее есть значение, и когда я вставляю точку останова в строку, где я получаю ошибку, и проверяю мое пространство имен, переменная w действительно является строкой.