Как я могу близко достичь?: Из C++/C# в Python?
В C# я мог бы легко написать следующее:
string stringValue = string.IsNullOrEmpty( otherString ) ? defaultString : otherString;
Есть ли быстрый способ сделать то же самое в Python, или я застрял с оператором "если"?
9 ответов
В Python 2.5 есть
A if C else B
который ведет себя так же, как?: в C. Однако, он не одобряется по двум причинам: удобочитаемость и тот факт, что обычно существует более простой способ решения проблемы. Например, в вашем случае:
stringValue = otherString or defaultString
@Dan
if otherString: stringValue = otherString else: stringValue = defaultString
Этот тип кода длиннее и выразительнее, но также более читабелен
Ну да, это дольше. Не уверен насчет "более выразительных" и "более читабельных". По крайней мере, ваше требование является спорным. Я бы даже сказал, что это неправильно, по двум причинам.
Во-первых, ваш код подчеркивает процесс принятия решений (довольно сильно). С другой стороны, условный оператор подчеркивает что-то еще, а именно значение (соответственно, присвоение указанного значения). И это именно то , чего хочет автор этого кода. Принятие решений действительно является побочным продуктом кода. Важной частью здесь является операция присваивания. Ваш код скрывает это назначение в большом количестве синтаксического шума: ветвления.
Ваш код менее выразителен, потому что он смещает акцент с важной части.
Даже тогда ваш код, вероятно, превзойдет некоторые неясные ASCII-произведения, такие как ?:
, Встроенный if
было бы предпочтительнее. Лично мне не нравится вариант, представленный в Python 2.5, потому что он задом наперед. Я бы предпочел что-то, что читается в том же потоке (направлении), что и троичный оператор C, но использует слова вместо символов ASCII:
C = if cond then A else B
Это выигрывает руки вниз.
К сожалению, C и C# не имеют такого выразительного утверждения. Но (и это второй аргумент) троичный условный оператор языков Си настолько давно установлен, что сам по себе стал идиомой. Тернарный оператор является такой же частью языка, как и "обычный" if
заявление. Поскольку это идиома, любой, кто знает язык, сразу же читает этот код правильно. Кроме того, это чрезвычайно короткий и лаконичный способ выражения этой семантики. На самом деле, это самый короткий путь, который можно себе представить. Это чрезвычайно выразительно, потому что не затеняет сущность ненужным шумом.
Наконец, Джефф Этвуд написал идеальный вывод: лучший код - это вовсе не код.
Это никогда не плохо писать понятный, выразительный код.
if otherString:
stringValue = otherString
else:
stringValue = defaultString
Этот тип кода длиннее и более выразителен, но также более читабелен и менее подвержен ошибкам или неправильному редактированию в будущем. Не бойтесь писать выразительно - читаемый код должен быть целью, а не побочным продуктом.
Есть несколько дубликатов этого вопроса, например
- Есть ли в Python троичный условный оператор?
- Какой лучший способ заменить тернарный оператор в Python?
По сути, в общих настройках кода pre-2.5 следует использовать это:
(condExp and [thenExp] or [elseExp])[0]
(учитывая, что condExp, thenExp и elseExp являются произвольными выражениями), поскольку это позволяет избежать ошибочных результатов, если thenExp вычисляет логическое значение False, сохраняя при этом оценку короткого замыкания.
Глава 4 diveintopython.net имеет ответ. Это называется и-или трюк в Python.
Я также обнаружил, что простое использование оператора "или" работает довольно хорошо. Например:
finalString = get_override() or defaultString
Если get_override() возвращает "" или None, он всегда будет использовать defaultString.
Кстати, j0rd4n, вы не пишите (пожалуйста, не!) Такой код на C#. Помимо того, что IsDefaultOrNull
на самом деле называется IsNullOrEmpty
это чистый код наворотов. C# предлагает оператор объединения для таких ситуаций:
string stringValue = otherString ?? defaultString;
Это правда, что это работает, только если otherString
является null
(а не пустой), но если это может быть обеспечено заранее (и часто это возможно), это делает код намного более читабельным.
Если бы вы использовали ruby, вы могли бы написать
stringValue = otherString.blank? ? defaultString : otherString;
встроенный blank?
Метод означает ноль или пустой.
Переходи на темную сторону...
Вы можете воспользоваться тем фактом, что логические выражения возвращают свое значение, а не только истинное или ложное состояние. Например, вы всегда можете использовать:
result = question and firstanswer or secondanswer
С оговоркой, что он не работает как троичный оператор, если firstanswer является ложным. Это связано с тем, что вопрос оценивается первым, предполагая, что он верен. Firstanswer возвращается, если firstanswer не ложен, поэтому такое использование не действует как троичный оператор. Однако, если вы знаете значения, обычно проблем не возникает. Примером может быть:
result = choice == 7 and "Seven" or "Another Choice"