Использовать выражение дважды в одной строке – как условие AND для форматирования строк?

Я нахожу, что во множестве разных проектов я пишу много кода, где мне нужно оценить (умеренно сложное, возможно дорогостоящее, чтобы оценить) выражение, а затем сделать с ним что-то (например, использовать его для форматирования строк), но только если выражение True / не-None.

Например, во многих местах я делаю что-то вроде следующего:

result += '%s '%( <complexExpressionForGettingX> ) if <complexExpressionForGettingX> else '' 

… который, по моему мнению, в основном является особым случаем более общей проблемы, требующей вернуть некоторую функцию выражения, но только если это выражение True, то есть:

 f( e() ) if e() else somedefault 

но без повторного ввода выражения (или переоценки его, если это дорогостоящий вызов функции).

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

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

 (lambda e: '%s ' % e if e else '')( <complexExpressionForGettingX> ) 

или написать мою собственную функцию полезности, например:

 def conditional(expr, formatStringIfTrue, default='') 

… но поскольку я делаю это во множестве разных кодовых оснований, я бы скорее использовал встроенную библиотечную функцию или какой-нибудь умный синтаксис python, если такая вещь существует

5 Solutions collect form web for “Использовать выражение дважды в одной строке – как условие AND для форматирования строк?”

Определенно, мне нравятся однострочники. Но иногда это неправильное решение.

В профессиональной разработке программного обеспечения, если размер команды составляет> 2, вы потратили больше времени на понимание кода, написанного кем-то другим, чем при написании нового кода. Представленные здесь однострочные вклады определенно сбивают с толку, поэтому просто выполните две строки (хотя вы упомянули несколько заявлений в своем сообщении):

 X = <complexExpressionForGettingX> result += '%s '% X if X else '' 

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

У Python нет области видимости ( есть ли эквивалент Python для Haskell 'let' ), по-видимому, потому, что злоупотребления и путаница синтаксиса перевешивают преимущества.

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

 result += next('%s '%(e) if e else '' for e in (<complexExpressionForGettingX>,)) 

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

 def cond_format(expr, form, alt): if expr: return form % expr else: return alt 

Применение:

 result += cond_format(<costly_expression>, '%s ', '') 

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

Для лучшей ясности я решил, что это должно быть реализовано как функция многократного использования (а не лямбда), поэтому в интересах других, я думал, что буду делиться с этой функцией, которую я наконец придумал, – которая достаточно гибкая, чтобы справиться с несколькими дополнительными строками формата аргументы (в дополнение к основному аргументу, используемому для определения того, нужно ли вообще форматировать); он также поставляется с pythondoc, чтобы показать правильность и проиллюстрировать использование (если вы не знаете, как работает функция «kwargs», просто игнорируйте ее, это всего лишь деталь реализации, и это был единственный способ, которым я мог видеть, чтобы реализовать необязательный defaultValue = kwarg, следующий переменный список аргументов строки формата).

 def condFormat(formatIfTrue, expr, *otherFormatArgs, **kwargs): """ Helper for creating returning the result of string.format() on a specified expression if the expressions's bool(expr) is True (ie it's not None, an empty list or an empty string or the number zero), or return a default string (typically '') if not. For more complicated cases where the operation on expr is more complicated than a format string, or where a different condition is required, use: (lambda e=myexpr: '' if not e else '%s ' % e) formatIfTrue -- a format string suitable for use with string.format(), eg "{}, {}" or "{1}, {0:d}". expr -- the expression to evaluate. May be of any type. defaultValue -- set this keyword arg to override >>> 'x' + condFormat(', {}.', 'foobar') 'x, foobar.' >>> 'x' + condFormat(', {}.', []) 'x' >>> condFormat('{}; {}', 123, 456, defaultValue=None) '123; 456' >>> condFormat('{0:,d}; {2:d}; {1:d}', 12345, 678, 9, defaultValue=None) '12,345; 9; 678' >>> condFormat('{}; {}; {}', 0, 678, 9, defaultValue=None) == None True """ defaultValue = kwargs.pop('defaultValue','') assert not kwargs, 'unexpected kwargs: %s'%kwargs if not bool(expr): return defaultValue if otherFormatArgs: return formatIfTrue.format( *((expr,)+otherFormatArgs) ) else: return formatIfTrue.format(expr) 

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

Вы закончите с чем-то вроде этого:

 ' '.join(map(str, filter(None, <iterable of <complexExpressionForGettingX>>))) 

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

 >>> ' '.join(map(str, filter(None, range(-3, 3)))) '-3 -2 -1 1 2' 

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

  • Можно ли применить mapmap с помощью groupby в пандах?
  • Как установить pymysql на AWS лямбда
  • Индекс за пределами диапазона при использовании лямбда
  • Подключение к базе данных Filemaker с использованием JDBC, Python и JayDeBeApi
  • Lambdas из понимания списка возвращает лямбду при вызове
  • Поиск среднего списка
  • Qt - слот подключения с аргументом, использующий лямбда
  • Подсчитайте количество строк между двумя датами BY ID в кадре данных Pandas GroupBy
  •  
    Interesting Posts for Van-Lav

    Блокировка LIRC Python Обходной путь сигнала не работает

    Как создать произвольную ортонормированную матрицу в python numpy

    Удаление символов не-ascii в файле csv

    Flask-WhooshAlchemy с существующей базой данных

    Условное оформление Python3?

    Почему невозможно напрямую преобразовать «1.7» в integer, не конвертируя сначала float?

    как печатать удобную покерную руку в python?

    Как я могу распечатать docstring файла Python при его выполнении?

    Как вызвать функцию со словарем, который содержит больше элементов, чем функция имеет параметры?

    Длительная медленная работа в представлении Django вызывает таймаут. В любом случае для Python вместо этого говорить AJAX?

    Изменение чертежей или обновление флеш-приложения во время выполнения

    Timedelta не определен

    Пример MySQL LOAD DATA LOCAL INFILE в python?

    functools.partial по методу класса

    Как я могу получить последнее измененное datetime для объектов S3 с помощью boto?

    Python - лучший язык программирования в мире.