Функция search — Python для сетевых инженеров

Toggle table of contents sidebar

Функция search:

  • используется для поиска подстроки, которая соответствует шаблону

  • возвращает объект Match, если подстрока найдена

  • возвращает None, если подстрока не найдена

Функция search подходит в том случае, когда надо найти только одно совпадение в строке, например, когда регулярное выражение описывает всю строку или часть строки.

Рассмотрим пример использования функции search в разборе лог-файла.

В файле log.txt находятся лог-сообщения с информацией о том, что один и тот же MAC слишком быстро переучивается то на одном, то на другом интерфейсе. Одна из причин таких сообщений — петля в сети.

Содержимое файла log.txt:

%SW_MATM-4-MACFLAP_NOTIF: Host 01e2.4c18.0156 in vlan 10 is flapping between port Gi0/16 and port Gi0/24
%SW_MATM-4-MACFLAP_NOTIF: Host 01e2.
4c18.0156 in vlan 10 is flapping between port Gi0/16 and port Gi0/24 %SW_MATM-4-MACFLAP_NOTIF: Host 01e2.4c18.0156 in vlan 10 is flapping between port Gi0/24 and port Gi0/19 %SW_MATM-4-MACFLAP_NOTIF: Host 01e2.4c18.0156 in vlan 10 is flapping between port Gi0/24 and port Gi0/16

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

Попробуем вычислить, между какими портами и в каком VLAN образовалась проблема. Проверка регулярного выражения с одной строкой из log-файла:

In [1]: import re
In [2]: log = '%SW_MATM-4-MACFLAP_NOTIF: Host 01e2.4c18.0156 in vlan 10 is flapping between port Gi0/16 and port Gi0/24'
In [3]: match = re.search(r'Host \S+ '
   ...:                   r'in vlan (\d+) '
   ...:                   r'is flapping between port '
   ...:                   r'(\S+) and port (\S+)', log)
   ...:

Регулярное выражение для удобства чтения разбито на части. В нём есть три группы:

В итоге, в группы попали такие части строки:

In [4]: match. groups()
Out[4]: ('10', 'Gi0/16', 'Gi0/24')

В итоговом скрипте файл log.txt обрабатывается построчно, и из каждой строки собирается информация о портах. Так как порты могут дублироваться, сразу добавляем их в множество, чтобы получить подборку уникальных интерфейсов (файл parse_log_search.py):

import re
regex = (r'Host \S+ '
         r'in vlan (\d+) '
         r'is flapping between port '
         r'(\S+) and port (\S+)')
ports = set()
with open('log.txt') as f:
    for line in f:
        match = re.search(regex, line)
        if match:
            vlan = match.group(1)
            ports.add(match.group(2))
            ports.add(match.group(3))
print('Петля между портами {} в VLAN {}'.format(', '.join(ports), vlan))

Результат выполнения скрипта такой:

$ python parse_log_search.py
Петля между портами Gi0/19, Gi0/24, Gi0/16 в VLAN 10

Попробуем получить параметры устройств из вывода sh cdp neighbors detail.

Пример вывода информации для одного соседа:

SW1#show cdp neighbors detail
-------------------------
Device ID: SW2
Entry address(es):
  IP address: 10. 1.1.2
Platform: cisco WS-C2960-8TC-L,  Capabilities: Switch IGMP
Interface: GigabitEthernet1/0/16,  Port ID (outgoing port): GigabitEthernet0/1
Holdtime : 164 sec
Version :
Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Mon 03-Mar-14 22:53 by prod_rel_team
advertisement version: 2
VTP Management Domain: ''
Native VLAN: 1
Duplex: full
Management address(es):
  IP address: 10.1.1.2

Задача получить такие поля:

  • имя соседа (Device ID: SW2)

  • IP-адрес соседа (IP address: 10.1.1.2)

  • платформу соседа (Platform: cisco WS-C2960-8TC-L)

  • версию IOS (Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9, RELEASE SOFTWARE (fc1))

И для удобства надо получить данные в виде словаря. Пример итогового словаря для коммутатора SW2:

{'SW2': {'ip': '10.
1.1.2', 'platform': 'cisco WS-C2960-8TC-L', 'ios': 'C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9'}}

Пример проверяется на файле sh_cdp_neighbors_sw1.txt.

Первый вариант решения (файл parse_sh_cdp_neighbors_detail_ver1.py):

import re
from pprint import pprint
def parse_cdp(filename):
    result = {}
    with open(filename) as f:
        for line in f:
            if line.startswith('Device ID'):
                neighbor = re.search(r'Device ID: (\S+)', line).group(1)
                result[neighbor] = {}
            elif line.startswith('  IP address'):
                ip = re.search(r'IP address: (\S+)', line).group(1)
                result[neighbor]['ip'] = ip
            elif line.startswith('Platform'):
                platform = re.search(r'Platform: (\S+ \S+),', line).group(1)
                result[neighbor]['platform'] = platform
            elif line.startswith('Cisco IOS Software'):
                ios = re.search(r'Cisco IOS Software, (.
+), RELEASE', line).group(1) result[neighbor]['ios'] = ios return result pprint(parse_cdp('sh_cdp_neighbors_sw1.txt'))

Тут нужные строки отбираются с помощью метода строк startswith. И в строке с помощью регулярного выражения получается требуемая часть строки. В итоге все собирается в словарь.

Результат выглядит так:

$ python parse_sh_cdp_neighbors_detail_ver1.py
{'R1': {'ios': '3800 Software (C3825-ADVENTERPRISEK9-M), Version 12.4(24)T1',
        'ip': '10.1.1.1',
        'platform': 'Cisco 3825'},
 'R2': {'ios': '2900 Software (C3825-ADVENTERPRISEK9-M), Version 15.2(2)T1',
        'ip': '10.2.2.2',
        'platform': 'Cisco 2911'},
 'SW2': {'ios': 'C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9',
         'ip': '10.1.1.2',
         'platform': 'cisco WS-C2960-8TC-L'}}

Все получилось как нужно, но эту задачу можно решить более компактно.

Вторая версия решения (файл parse_sh_cdp_neighbors_detail_ver2.

py):

import re
from pprint import pprint
def parse_cdp(filename):
    regex = (r'Device ID: (?P<device>\S+)'
             r'|IP address: (?P<ip>\S+)'
             r'|Platform: (?P<platform>\S+ \S+),'
             r'|Cisco IOS Software, (?P<ios>.+), RELEASE')
    result = {}
    with open(filename) as f:
        for line in f:
            match = re.search(regex, line)
            if match:
                if match.lastgroup == 'device':
                    device = match.group(match.lastgroup)
                    result[device] = {}
                else:
                    result[device][match.lastgroup] = match.group(
                        match.lastgroup)
    return result
pprint(parse_cdp('sh_cdp_neighbors_sw1.txt'))

Пояснения ко второму варианту:

  • в регулярном выражении описаны все варианты строк через знак или |

  • без проверки строки ищется совпадение

  • если совпадение найдено, проверяется метод lastgroup

  • метод lastgroup возвращает имя последней именованной группы в регулярном выражении, для которой было найдено совпадение

  • если было найдено совпадение для группы device, в переменную device записывается значение, которое попало в эту группу

  • иначе в словарь записывается соответствие „имя группы“: соответствующее значение

Результат будет таким же:

$ python parse_sh_cdp_neighbors_detail_ver2. py
{'R1': {'ios': '3800 Software (C3825-ADVENTERPRISEK9-M), Version 12.4(24)T1',
        'ip': '10.1.1.1',
        'platform': 'Cisco 3825'},
 'R2': {'ios': '2900 Software (C3825-ADVENTERPRISEK9-M), Version 15.2(2)T1',
        'ip': '10.2.2.2',
        'platform': 'Cisco 2911'},
 'SW2': {'ios': 'C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9',
         'ip': '10.1.1.2',
         'platform': 'cisco WS-C2960-8TC-L'}}

Оптимизация гиперпараметров с помощью поиска по сетке и случайного поиска в Python / Хабр

Введение

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

Например, модель логистической регрессии имеет различные решатели, использующиеся для поиска коэффициентов, которые могут дать нам наилучший из возможных результатов. Каждый решатель использует свой алгоритм для поиска оптимального результата, и ни один из них не является однозначно лучше, чем другой. Трудно сказать, какой решатель будет работать качественнее всего на вашем наборе данных (датасете), пока вы не попробуете их все.

Лучший гиперпараметр субъективен и отличается для каждого датасета. Библиотека Scikit-Learn в Python имеет набор гиперпараметров по умолчанию, которые достаточно хорошо работают для всех моделей, но они не обязательно являются наилучшими для каждой из проблем.

Единственный способ найти наиболее подходящие гиперпараметры для вашего датасета — это метод проб и ошибок, что и является основной концепцией оптимизации гиперпараметров.

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

Существуют две популярные техники, используемые для оптимизации гиперпараметров, — сеточный и случайный поиск.

Поиск по сетке

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

Затем используется метод поиска по сетке для размещения этих гиперпараметров в матрице, и модель обучается на каждой комбинации значений гиперпараметров.

После этого выбирается модель с наилучшими показателями.

Случайный поиск

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

Эта техника вместо исчерпывающего поиска делает случайную выборку из сетки гиперпараметров.

Мы можем указать общее количество попыток случайного поиска, прежде чем будет получена наилучшая модель.

Теперь, когда у вас есть базовое понимание того, как работают случайный поиск и поиск по сетке, я покажу, как реализовать эти методы с помощью библиотеки Scikit-Learn.

Оптимизация классификатора Random Forest (случайный лес) с помощью поиска по сетке и случайного поиска

Шаг 1: Загрузка набора данных

Загрузите датасет Wine Quality на сайте Kaggle и введите следующие строки кода, чтобы считать его с помощью библиотеки Pandas:

import pandas as pd
df = pd. read_csv('winequality-red.csv')
df.head()

Верхняя часть датафрейма выглядит следующим образом:

Шаг 2: Предварительная обработка данных

Целевая переменная «quality» (качество) содержит значения в диапазоне от 1 до 10.

Мы превратим ее в задачу бинарной классификации, присвоив всем пунктам данных со значением качества меньше или равным 5 значение 0, а остальным результатам — значение 1:

import numpy as np
df['target'] = np.where(df['quality']>5, 1, 0)

Давайте разделим зависимые и независимые переменные в этом датафрейме:

df2 = df.drop(['quality'],axis=1)
X = df2.drop(['target'],axis=1)
y = df2[['target']]

Шаг 3: Построение модели

Теперь давайте создадим классификатор случайного леса. Мы будем выполнять настройку гиперпараметров этой модели, для создания наилучшего алгоритма под наш датасет:

from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier()

Шаг 4: Реализация поиска по сетке с помощью Scikit-Learn

Определение пространственного диапазона гиперпараметров

Сейчас мы попробуем настроить следующий набор гиперпараметров этой модели:

  1. «Max_depth»: Этот гиперпараметр представляет максимальный уровень (глубину) каждого дерева в модели случайного леса. Более глубокое дерево показывает хорошие результаты и собирает много информации об обучающих данных, но плохо поддается обобщению для тестовых данных. По умолчанию в библиотеке Scikit-Learn это значение установлено в «None», что значит, такие деревья оставлены для полного расширения.

  2. «Max_features»: Максимальное количество признаков, которое модели случайного леса разрешается опробовать при каждом разбиении. По умолчанию в Scikit-Learn это значение устанавливается равным квадратному корню из общего числа переменных в наборе данных.

  3. «N_estimators»: Количество деревьев решений в лесу. По умолчанию в Scikit-Learn число оценщиков (estimators) равно 10.

  4. «Min_samples_leaf»: Минимальное количество образцов, необходимое для нахождения в листовом узле каждого дерева. В Scikit-Learn значение по умолчанию равно 1.

  5. «Min_samples_split»: Минимальное количество образцов, необходимое для разбиения внутреннего узла каждого дерева. В Scikit-Learn значение по умолчанию равно 2.

Теперь мы создадим словарь из множества возможных значений для всех вышеперечисленных гиперпараметров. Это также называется пространством гиперпараметров, и мы будем перебирать их, чтобы найти наилучшую комбинацию аргументов:

grid_space={'max_depth':[3,5,10,None],
              'n_estimators':[10,100,200],
              'max_features':[1,3,5,7],
              'min_samples_leaf':[1,2,3],
              'min_samples_split':[1,2,3]
           }

Запуск поиска по сетке

Теперь нам нужно выполнить поиск, чтобы найти наилучшую комбинацию гиперпараметров для модели:

from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(rf,param_grid=grid_space,cv=3,scoring='accuracy')
model_grid = grid.fit(X,y)

Оценка результатов моделирования

Наконец, давайте выведем самую высокую степень точности модели, а также набор гиперпараметров, которые обеспечили такой результат:

print('Best hyperparameters are: '+str(model_grid. best_params_))
print('Best score is: '+str(model_grid.best_score_))

Лучшая модель дала оценку точности приблизительно 0,74, а ее гиперпараметры следующие:

Теперь давайте применим случайный поиск на том же датасете и посмотрим, сможем ли мы получить подобные результаты.

Шаг 5: Реализация случайного поиска с помощью Scikit-Learn

Определение области значений гиперпараметров

Теперь давайте определим диапазон значений гиперпараметров для реализации случайного поиска. Эта область параметров может иметь больший диапазон значений, чем та, которую мы построили для поиска по сетке, поскольку случайный поиск не пытается полностью опробовать все комбинации гиперпараметров.

Он случайным образом выбирает гиперпараметры, чтобы найти лучшие из них, и это означает, что в отличие от сеточного поиска, случайный поиск может быстро перебрать большое количество значений.

from scipy.stats import randint
rs_space={'max_depth':list(np. arange(10, 100, step=10)) + [None],
              'n_estimators':np.arange(10, 500, step=50),
              'max_features':randint(1,7),
              'criterion':['gini','entropy'],
              'min_samples_leaf':randint(1,4),
              'min_samples_split':np.arange(2, 10, step=2)
         }

Запуск случайного поиска

Выполните следующие строки кода для запуска случайного поиска модели: (Обратите внимание, что мы указали n_iter=500, значит, случайный поиск будет выполняться 500 раз, прежде чем будет выбрана лучшая модель. Вы можете поэкспериментировать с другим числом итераций, чтобы увидеть, сколько из них дает оптимальные результаты. Имейте в виду, что большое количество итераций приведет к улучшению качества производительности, но при этом будет достаточно трудоемким).

from sklearn.model_selection import RandomizedSearchCV
rf = RandomForestClassifier()
rf_random = RandomizedSearchCV(rf, space, n_iter=500, scoring='accuracy', n_jobs=-1, cv=3)
model_random = rf_random. fit(X,y)

Оценка результатов моделирования

Теперь выполните следующие строки кода, чтобы вывести лучшие гиперпараметры, найденные методом случайного поиска, а также самую высокую точность самой удачной модели:

print('Best hyperparameters are: '+str(model_random.best_params_))
print('Best score is: '+str(model_random.best_score_))

Лучшие гиперпараметры, найденные методом случайного поиска, следующие:

Самая высокая точность из всех построенных моделей также составляет примерно 0,74.

Обратите внимание, что поиск по сетке, и случайный поиск достаточно хорошо справились с этим датасетом. Имейте в виду, что если вы запустите случайный поиск на том же коде, ваши результаты могут сильно отличаться от того, что я показал выше.

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

Полный код

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

# imports
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from scipy.stats import randint
from sklearn.model_selection import RandomizedSearchCV
# reading the dataset 
df = pd.read_csv('winequality-red.csv')
# preprocessing 
df['target'] = np.where(df['quality']>5, 1, 0)
df2 = df.drop(['quality'],axis=1)
X = df2.drop(['target'],axis=1)
y = df2[['target']]
# initializing random forest
rf = RandomForestClassifier()
# grid search cv
grid_space={'max_depth':[3,5,10,None],
              'n_estimators':[10,100,200],
              'max_features':[1,3,5,7],
              'min_samples_leaf':[1,2,3],
              'min_samples_split':[1,2,3]
           }
grid = GridSearchCV(rf,param_grid=grid_space,cv=3,scoring='accuracy')
model_grid = grid.fit(X,y)
# grid search results
print('Best grid search hyperparameters are: '+str(model_grid. best_params_))
print('Best grid search score is: '+str(model_grid.best_score_))
# random search cv
rs_space={'max_depth':list(np.arange(10, 100, step=10)) + [None],
              'n_estimators':np.arange(10, 500, step=50),
              'max_features':randint(1,7),
              'criterion':['gini','entropy'],
              'min_samples_leaf':randint(1,4),
              'min_samples_split':np.arange(2, 10, step=2)
          }
rf = RandomForestClassifier()
rf_random = RandomizedSearchCV(rf, rs_space, n_iter=500, scoring='accuracy', n_jobs=-1, cv=3)
model_random = rf_random.fit(X,y)
# random random search results
print('Best random search hyperparameters are: '+str(model_random.best_params_))
print('Best random search score is: '+str(model_random.best_score_))

Поиск по сетке и случайный поиск — какой из них использовать?

Если вы когда-нибудь окажетесь перед выбором между поиском по сетке и случайным поиском, вот несколько советов, которые помогут вам решить, какой из них использовать:

  1. Используйте поиск по сетке, если у вас уже есть примерный диапазон известных значений гиперпараметров, которые будут работать хорошо. Убедитесь, что область значений параметров невелика, так как поиск по сетке может занять очень много времени. 

  2. Применяйте случайный поиск в широком диапазоне значений, если у вас еще нет представления о параметрах, которые будут хорошо работать в вашей модели. Случайный поиск быстрее, чем поиск по сетке, и его всегда следует использовать, когда у вас большая область значений параметров.

  3. Для получения наилучших результатов целесообразно использовать как случайный поиск, так и поиск по сетке.

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


В феврале в рамках специализации Machine Learning в Otus пройдут два бесплатных открытых урока, на которые могут записаться все заинтересованные. Темы вебинаров и ссылки на регистрацию ниже:

  • На первом уроке мы разберем основы Machine Learning и поговорим о такой востребованной области, как Data Science.

  • На втором уроке освоим популярный ML-алгоритм – «дерево решений». Поговорим о том, для каких задач его используют в машинном обучении и как правильно его применять на практике.

Будем рады всем участникам.

Как искать в Python

Надежные ответы на вопросы разработчиков

Grokking the Behavioral Interview

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

Алгоритмы поиска

Алгоритмы поиска используются для извлечения или поиска любого элемента из заданного набора структур данных.

В зависимости от методов алгоритмы поиска подразделяются на 2 типа :

1. Линейный поиск

2. Двоичный поиск

Линейный поиск

  • Метод, используемый для поиска определенного элемента или значения в списке или массиве путем последовательного обхода каждого элемента, пока нужный элемент не будет найден.

  • Также известен как последовательный поиск.

Алгоритм/процедура линейного поиска:

  1. Начинает с крайнего левого элемента заданного массива или списка и последовательно сравнивает элемент x с каждым элементом массива или списка.

  2. Если x совпадает с любым из элементов, вернуть значение индекса.

  3. Если x не совпадает ни с одним из элементов в списке или массиве, вернуть -1 или элемент не найден.

 

def LinearSearch(lst,x):

для i в диапазоне(len(lst)):

, если x == lst[i]:

print("x(элемент) найден по индексу=",i)

break

else:

print("x(элемент) не найден")

lst=[1, 2, 3 , 4, 5, 6, 7, 8, 9, 10]

x=7

print(lst)

print("Элемент, необходимый для поиска, x =",x)

LinearSearch(lst,x) )

Бинарный поиск

  • Также известен как интервальный поиск
  • Более эффективен, чем линейный поиск.
  • Использует алгоритм поиска «разделяй и властвуй»

Алгоритм/процедура бинарного поиска

  1. Сортировка списка элементов.
  2. Найти средний элемент в отсортированном списке.
  3. Сравните ключ со средним элементом
  4. Если ключ соответствует среднему элементу, найден ключ сообщения печати и выполнение останавливается.
  5. В противном случае, если ключ больше среднего элемента, ключ ищется в правом подсписке и снова начинается с шага 3.
  6. В противном случае, если ключ меньше среднего элемента, ключ ищется в левом подсписке и снова начинается с шага 3.
  7. Если ключ по-прежнему не соответствует, вернуть ключ сообщения, который не был найден.
 

по определению BinarySearch(lst,x):

первый=0

последняя=длина(первая)-1

флаг = Ложь

while (первый<=последний, а не флаг):

середина= (первый + последний)//2

, если lst[mid] == x:

флаг = Истина

elif x>lst[середина]:

первый= середина +1

еще:

последний = середина 1

если флаг == Истина:

print("Ключ найден")

еще:

печать("ключ не найден")

лст=[1, 3, 4, 5, 8, 9, 6, 10, 7]

список. сортировка()

печать(л)

х = 7

print("элемент для поиска, x =",x)

BinarySearch(lst,x)

СВЯЗАННЫЕ ТЕГИ

линейный поиск

бинарный поиск

python

УЧАСТНИК

Abhishek Pusuluri

Лицензия: Creative Commons-Attribution-ShareAlike 4.0 (CC-BY-SA 4.0)

python — Поиск индекса элемента в списке

Поиск индекса элемента по списку, содержащему его в Python

Для списка ["foo", "bar", "baz"] и элемента в списке "bar" , какой самый чистый способ получить его индекс (1) в Python?

Ну да, есть метод index, который возвращает индекс первого вхождения:

 >>> л = ["фу", "бар", "баз"]
>>> l.index('бар')
1
 

Есть несколько проблем с этим методом:

  • если значение отсутствует в списке, вы получите ValueError
  • если в списке присутствует более одного значения, вы получите индекс только для первого из них

Нет значений

Если значение может отсутствовать, необходимо отловить ValueError .

Вы можете сделать это с помощью многоразового определения, подобного этому:

 индекс определения (a_list, значение):
    пытаться:
        вернуть a_list.index (значение)
    кроме ValueError:
        возврат Нет
 

И используйте это так:

 >>> print(index(l, 'quux'))
Никто
>>> print(index(l, 'bar'))
1
 

И недостатком этого является то, что у вас, вероятно, будет проверка, является ли возвращаемое значение или не None:

 result = index(a_list, value)
если результат не None:
    сделать_что-то (результат)
 

Более одного значения в списке

Если у вас может быть больше вхождений, вы не получите полную информацию с list.index :

 >>> l.append('bar')
>>> л
['фу', 'бар', 'баз', 'бар']
>>> l.index('bar') # ничего в индексе 3?
1
 

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

 >>> [индекс для индекса, v в enumerate(l), если v == 'bar']
[1, 3]
>>> [индекс для индекса, v в enumerate(l), если v == 'boink']
[]
 

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

 indexes = [index for index, v in enumerate(l) if v == 'трахаться']
для индекса в индексах:
    делать_что-то (индекс)
 

Лучшая обработка данных с помощью pandas

Если у вас есть pandas, вы можете легко получить эту информацию с помощью объекта Series:

 >>> import pandas as pd
>>> серия = pd. Series(l)
>>> серия
0 фу
1 бар
2 баз
3 бар
тип: объект
 

Проверка сравнения вернет серию логических значений:

 >>> series == 'bar'
0 Ложь
1 правда
2 Ложь
3 Правда
тип: логический
 

Передайте эту серию логических значений в серию с помощью нижнего индекса, и вы получите только соответствующие элементы:

 >>> series[series == 'bar']
1 бар
3 бар
тип: объект
 

Если вам нужны только индексы, атрибут index возвращает ряд целых чисел:

 >>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
 

И если вы хотите, чтобы они были в списке или кортеже, просто передайте их конструктору:

 >>> list(series[series == 'bar'].index)
[1, 3]
 

Да, вы могли бы использовать понимание списка с enumerate, но, на мой взгляд, это не так элегантно — вы выполняете тесты на равенство в Python, вместо того, чтобы позволить встроенному коду, написанному на C, обрабатывать это:

 >> > [i для i, значение в enumerate(l), если значение == 'bar']
[1, 3]
 

Проблема XY спрашивает о вашей попытке решения, а не о вашей реальной проблеме.

Как вы думаете, зачем нужен индекс для элемента в списке?

Если вы уже знаете значение, какое вам дело до того, где оно находится в списке?

Если значения нет, перехват ValueError довольно многословен, и я предпочитаю этого избегать.

В любом случае я обычно перебираю список, поэтому я обычно сохраняю указатель на любую интересную информацию, получая индекс с перечислением.

Если вы обрабатываете данные, вам, вероятно, следует использовать pandas, у которого есть гораздо более элегантные инструменты, чем обходные пути на чистом Python, которые я показал.

Я не помню, чтобы мне самому понадобился list.index . Однако я просмотрел стандартную библиотеку Python и нашел для нее несколько отличных применений.

В idlelib для графического пользовательского интерфейса и разбора текста существует множество применений.

Модуль ключевого слова использует его для поиска маркеров комментариев в модуле, чтобы автоматически регенерировать список ключевых слов в нем посредством метапрограммирования.