Использовать выражение дважды в одной строке – как условие 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' 

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

  • Как понять закрытие в лямбда?
  • Эффективно вычислять частоту слов в строке
  • Странное поведение лямбды в понимании списка
  • Как я могу вызвать объект GUI или больше из основного класса
  • странное поведение с lamba: getattr (obj, x) внутри списка
  • Получить ftp.retrlines для печати содержимого файла в строку
  • Python Только для чтения файловая система Ошибка с S3 и Lambda при открытии файла для чтения
  • AWS Python Lambda с Oracle
  • Вложенные области и Lambdas
  • Однострочное выражение «для» Python
  • Лямбда-функция для классов в python?
  • Python - лучший язык программирования в мире.