python, ключевое слово "a in b", как насчет нескольких a? - PullRequest
15 голосов
/ 18 апреля 2009

Мои приключения в 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."

Конечно, регулярные выражения могут помочь, но использование регулярных выражений потребует большого количества подробного кода и не так ясно, как "а в б". Есть ли другие способы Pythonic?

Ответы [ 7 ]

46 голосов
/ 18 апреля 2009
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() принимает итерацию и проверяет, все ли / все из них оцениваются как истинное значение. Объедините это с генератором выражений, и вы сможете проверить несколько элементов.

7 голосов
/ 18 апреля 2009

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

6 голосов
/ 19 апреля 2009

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

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() более читабелен.

1 голос
/ 07 января 2019

Это должно быть старое сообщение, теперь самый простой способ сделать это с помощью списка:

a = "some long text which may or may not include bononos or cabbages"
alternatives = ["apple", "banana", "riverdale"]
if a in alternatives:
    print("Hm?")
1 голос
/ 18 апреля 2009

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

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

Я думаю, что их легче читать, чем использовать any или all, но их нужно конвертировать в наборы. Так как вас интересует пересечение и удержание, вы можете в первую очередь подумать о том, чтобы сделать их множествами.

1 голос
/ 18 апреля 2009

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

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

РЕДАКТИРОВАТЬ: Не знал более питонический any(). Вероятно, лучше использовать это на python.

EDIT2: добавлены операторы break и исправлен регистр all .

0 голосов
/ 18 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...