Я кто-то из JavaScript.

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

i = next((i for i, entry in enumerate(toc[key]) if ('file' in entry and entry['file'] == name) or ('guide_directory' in entry and entry['guide_directory'] == name)), None)
-2
jchi2241 2 Июл 2019 в 06:29

5 ответов

Лучший ответ

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

i = next((i for i, entry in enumerate(toc[key]) 
            if ('file' in entry and entry['file'] == name) or 
               ('guide_directory' in entry and 
                entry['guide_directory'] == name)),
         None)

Существует некоторый возможный рефакторинг

('file' in entry and entry['file'] == name)`

Возможно

entry.get('file') == name

То же самое с ('guide_directory' in entry and entry['guide_directory'] == name)

Полагаю, вышесказанное справедливо и для вашего случая,

i = next((i for i, entry in enumerate(toc[key]) 
            if name and name in (entry.get('file'), entry.get('guide_directory')),
         None)

Если вы уверены, что имя не None, это еще короче

i = next((i for i, entry in enumerate(toc[key]) 
            if name in (entry.get('file'), entry.get('guide_directory')),
         None)
1
geckos 2 Июл 2019 в 04:05

Вот более краткая версия:

next(
   (i for i, entry in enumerate(toc[key]) if name in {
             entry.get('file'),
            entry.get('guide_directory')}),
   None)
1
Kasramvd 2 Июл 2019 в 03:37

Если name не может быть None, вы можете использовать dict.get:

i = next((i for i, entry in enumerate(toc[key]) if entry.get('file') == name or entry.get('guide_directory') == name), None)

Тогда in:

i = next((i for i, entry in enumerate(toc[key]) if name in (entry.get('file'), entry.get('guide_directory')), None)

Затем сделайте функцию:

def find_index(iterable, predicate):
    return next((i for i, x in enumerate(iterable) if predicate(x)), None)


i = find_index(toc[key], lambda entry:
        name in (entry.get('file'), entry.get('guide_directory')))
0
Ry- 2 Июл 2019 в 03:38

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

Например

foobar = "This is a really really long string that could not normally doesnt look very good because its too long for a simple line of code"

foobar = (
    "This is a really really long string "
    "that could not normally doesnt look "
    "very good because its too long for a "
    "simple line of code"
)

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

i = next(
    (
        i for i, entry in enumerate(toc[key]) 
        if (
            entry.get('file') == name 
            or entry.get('guide_directory') == name
        )
    ),
    None,
)

Другой стиль - разбить сложную логику на собственный метод. Это позволяет вам как модульное тестирование внутреннего компонента, так и возможное повторное использование позже. Вот как я могу написать это заявление:

def valid_entry(name: str, entry: Dict[str, Any]) -> bool:
    return (
       entry.get('file') == name 
       or entry.get('guide_directory') == name
    )

generator = (
    i for i, entry in enumerate(toc[key]) 
    if valid_entry(name, entry)
)
i = next(generator, None)
0
flakes 2 Июл 2019 в 03:46

Вы должны использовать get для dict s вместо проверки, является ли ключ in dict.

i = next((i for i, entry in enumerate(toc[key]) 
            if entry.get('file') == name or 
               entry.get('guide_directory') == name),
         None)
0
Saswat Padhi 2 Июл 2019 в 03:38