Я наткнулся на сторонний код Python, который гласил:
count = [remaining, readlen][remaining > readlen]
Посмотрев на это немного, я должен спросить: есть ли случаи, когда эта конструкция НЕ эквивалентна:
count = min(readlen, remaining)
то есть есть ли между ними какие-либо функциональные различия?
min()
, вероятно, не определен в терминах оператора >
, поэтому перегрузка может изменить результат, не так ли?
@AllanWind это просто синтаксис Python, который использует [] для списков и индексации
@gwr Да, я знаю, я говорил о >
Ах, ок. stackoverflow.com/questions/45308212/… предполагает, что встроенная функция min просто вызовет сравнение на итераторе
Это будет зависеть от методов сравнения . Например. если бы __lt__
существовало и всегда возвращалось True
(что, по общему признанию, было бы немного странно), результаты были бы противоположны друг другу.
Ух ты, какой способ написать код, который потом будет сложно понять! Вопрос внимательного понимания этого кода — отличный вопрос, но я надеюсь, что никто не возьмет это и не начнет использовать.
@joanis это обычная конструкция в кодовом гольфе, которая служит руководством по антистилю.
int
, что делает эти две конструкции эквивалентными в данном случае.
@qwr Верно, я думаю, что код-гольф никогда не сводится к разборчивости. Хотя [a,b][a<b]
на 2 символа длиннее, чем min(a,b)
, последний все равно следует отдавать предпочтение, даже в коде гольфа. Но я понимаю суть.
@AllanWind Сначала он попробует __lt__
(<
), а затем вернется к __gt__
(>
), если __lt__
не определен.
Первый сравнивает remaining > readlen
, а второй сравнивает remaining < readlen
. Это предназначено?
@qwr Взятие минимального значения *iterable не имеет значения, потому что OP использует форму с несколькими аргументами min()
, а не форму с одним аргументом.
Было ли переключение операндов намеренным? min
возвращает первый минимальный объект, если оба равны. Нечетная конструкция делает то же самое. Переключение порядка меня, кажется, сбивает с толку.
Чтобы сделать их эквивалентными, нам нужно поменять знак неравенства (и список) в первом. Если мы поменяем операнды в последнем, то логически будет то же самое, но разница в том, какой из __gt__
и __lt__
вызывается, все равно есть. Однако реальный вопрос заключается в том, хотел ли ОП знать об этих незначительных различиях или о более широкой картине.
Предположим a == b
. В этом случае [a,b][a>b]
возвращает a
, поскольку a>b
оценивается как False
, которое затем преобразуется в 0
. Но min(b, a)
возвращает b
(первый аргумент).
Это не относится к числам, но может иметь значение, если a
и b
являются изменяемыми объектами, например списками:
>>> a = [1, 2]
>>> b = [1, 2]
>>> c = [a, b][a>b]
>>> c is a
True
>>> c is b
False
>>> c.append(3)
>>> a
[1, 2, 3]
>>> b
[1, 2]
При использовании списков имеет значение, какой из двух равных объектов будет выбран.
Обратите внимание, что простая замена аргументов min
на min(a, b)
устранит эту разницу.
Ах да, равенство не означает одинаковый объектный регистр
Для чисел разных типов действительно есть заметная разница. a = 1; b = 1.0
затем [a, b][a > b]
→ 1
и min(b, a)
→ 1.0
Теперь ясно, что мне следовало написать min(a, b)
, а не min(b, a)
, но когда я задавал вопрос, это было не так очевидно! Спасибо! (Но да, это не пример кода для подражания!)
Обе конструкции задают count
меньшим из remaining
и readlen
, поэтому не будет случаев, когда они дают разные результаты.
Что, если они равны, но не являются одним и тем же объектом?
Это эквивалентно (a > b)? b : a, что также является классической мини-идиомой в C. Поэтому я думаю, что это то же самое, по крайней мере, для целых чисел.