Python, ключевое слово "a in b", как насчет нескольких a?

Мои приключения в Python продолжаются, и мои любимые книги снова молчат. Python предлагает встроенный способ проверить, находится ли переменная внутри итерабельного объекта, используя ключевое слово "in":

if "a" in "abrakadabra" :
  print "it is definitely here"

Но можно ли проверить, включено ли в список более одного элемента (любой)? В настоящее время я использую синтаксис ниже, но он длинный:

if "// @in " in sTxt or "// @out " in sTxt or "// @ret " in sTxt or <10 more>
  print "found."

Конечно, регулярные выражения могут помочь, но с помощью регулярных выражений будет много многословного кода и будет не так ясно, как "a in b". Есть ли еще какие-нибудь питонические пути?

Ответы

Ответ 1

alternatives = ("// @in ", "// @out ", "// @ret ")
if any(a in sTxT for a in alternatives):
    print "found"

if all(a in sTxT for a in alternatives):
   print "found all"

any() и all() берет iterable и проверяет, действительно ли они/все они оцениваются с истинным значением. Объедините это с выражением генератора, и вы можете проверить несколько элементов.

Ответ 2

any(snippet in text_body for snippet in ("hi", "foo", "bar", "spam"))

Ответ 3

Если вы тестируете множество строк для одних и тех же слов, может быть быстрее скомпилировать их как регулярное выражение. например:

import  re
words = ["// @in ", "// @out ", "// @ret "] + ["// @test%s " % i for i in range(10)]

my_regex = re.compile("|".join(map(re.escape, words)))

for line in lines_to_search:
    if my_regex.search(line):  print "Found match"

Некоторые быстрые сроки показывают, что это обычно быстрее, чем подход any(word in theString for word in words). Я тестировал оба подхода с разным текстом (короткий/длинный с/без совпадений). Вот результаты:

         { No keywords  } |  {contain Keywords }
         short    long       short    long
regex  : 0.214    27.214     0.147    0.149
any in : 0.579    81.341     0.295    0.300

Если производительность не имеет значения, подход any() более читабельен.

Ответ 4

Если вы хотите любой чек, вы должны использовать это:

inthere = False
checks = ('a', 'b')

for check in checks:
    if check in 'abrakadabra':
        inthere = True
        break

Если вы хотите все проверить, вы можете использовать это:

inthere = True
checks = ('a', 'b')

for check in checks:
    if check not in 'abrakadabra':
        inthere = False
        break

EDIT: Не знаю, больше pythonic any(). Вероятно, лучше использовать это на python.

EDIT2: Добавлены инструкции break и исправлены все случаи.

Ответ 5

Вы также можете использовать установить методы и операторы:

not alternatives.isdisjoint(sTxt)  # for "any"
(alternatives & sTxt) != set()  # Again, the intersection is nonempty
alternatives <= sTxt  # for "all"

Я думаю, что их легче читать, чем использовать все или все, но вам нужно преобразовать свои коллекции в группы. Поскольку пересечение и сдерживание - это то, о чем вы заботитесь, вы можете подумать о том, чтобы сделать их наборы в первую очередь.

Ответ 6

В синтаксисе нет встроенного способа сделать это. Однако вы можете использовать функцию "any", чтобы упростить ее, как показали @MizardX и @Benjamin Peterson.