2009-04-18 3 views
15

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

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." 

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

ответ

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

+5

Я добавил ссылки на документацию, поэтому С.Лотт не уменьшает вас;) При всей серьезности, однако, рекомендуется ссылаться на документы, надеясь, что вы не против. –

+0

Совсем нет. Благодарю. –

7

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

0

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

1

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

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: Добавлены операторы разрыва и исправлены все -case.

1

Вы также можете использовать set methods and operators:

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

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

+0

Не работает, если sTxt - это строка. –

+0

В моем ответе упоминается, что эти объекты должны быть множествами. – allyourcode

6

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

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() подход является более читаемым.

+0

\ o/Приятно иметь контрольные точки с запросом «может быть быстрее ..»! – dbr

Смежные вопросы