Почему Python не имеет знаковой функции?

Я не могу понять, почему Python не имеет a sign функция. Это имеет abs встроенный (который я рассматриваю signсестра), но нет sign.

В python 2.6 существует даже a copysign функция (в математике), но никакой знак. Почему беспокойство для записи a copysign(x,y) когда Вы могли просто записать a sign и затем доберитесь copysign непосредственно от abs(x) * sign(y)? Последний был бы намного более ясным: x со знаком y, тогда как с copysign необходимо помнить, является ли это x со знаком y или y со знаком x!

Очевидно, sign(x) не обеспечивает что-то большее чем cmp(x,0), но это было бы намного более читаемо, что это также (и для значительно читаемого языка как Python, это будет большим плюс).

Если я был разработчиком Python, я был бы другой путь arond: нет cmp встроенный, но a sign. Когда Вам нужно cmp(x,y), Вы могли просто сделать a sign(x-y) (или, еще лучше для нечислового материала, просто x> y - конечно, это должно было потребовать sorted принятие булевской переменной вместо целочисленного компаратора). Это также было бы более ясно: положительный, когда x>y (тогда как с cmp необходимо помнить конвенцию, положительную, когда первое больше, но это могло быть наоборот). Конечно, cmp имеет смысл в ее собственном по другим причинам (например, при сортировке нечисловых вещей, или если Вы хотите, чтобы вид был стабилен, который не является возможным использованием только с булевской переменной),

Так, вопрос: почему разработчик (разработчики) Python решал уехать sign функция из языка? Почему heck беспокоятся copysign и не его родитель sign?

Я пропускаю что-то?

РЕДАКТИРОВАНИЕ - после комментария Peter Hansen. Достаточно ярмарка, что Вы не использовали его, но Вы не сказали, для чего Вы используете Python. За 7 лет, что я использую Python, мне был нужен он бесчисленные времена, и последней является солома, которая сломала позвоночник верблюда!

Да, можно передать cmp вокруг, но 90% времен, что я должен был передать его, были в идиоме как lambda x,y: cmp(score(x),score(y)) это работало бы со знаком очень хорошо.

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

216
задан malana 29 July 2015 в 07:02
поделиться

3 ответа

РЕДАКТИРОВАНИЕ:

Действительно был патч , который включал знак() в математике , но он не был принят, потому что они не согласились с , что он должен возвращаться во всех краевых случаях (+/-0, +/-nan), etc)

Поэтому они решили реализовать только копирайтинг, который (хотя и более подробный) может быть использован для делегирования конечному пользователю желаемого поведения для краевых случаев - что иногда может потребовать вызова на cmp(x,0).


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

copysign(x,y):
Return x with the sign of y.

Самое главное, что copysign - это суперсеть знака sign! Вызов копи-сигнала с x=1 - это то же самое, что и функция знака . Поэтому вы можете просто использовать copysign и забыть об этом.

>>> math.copysign(1, -4)
-1.0
>>> math.copysign(1, 3)
1.0

Если вам надоело передавать целых два аргумента, вы можете реализовать sign таким образом, и он все равно будет совместим с IEEE-функцией, упомянутой другими:

>>> sign = functools.partial(math.copysign, 1) # either of these
>>> sign = lambda x: math.copysign(1, x) # two will work
>>> sign(-4)
-1.0
>>> sign(3)
1.0
>>> sign(0)
1.0
>>> sign(-0.0)
-1.0
>>> sign(float('nan'))
-1.0

Во-вторых, обычно, когда вам нужен знак чего-то, вы просто умножаете его на другое значение. И, конечно же, в основном это то, что делает copysign.

Так что вместо:

s = sign(a)
b = b * s

Вы можете просто сделать:

b = copysign(b, a)

И да, я удивлен, что вы используете Python в течение 7 лет и думаю, что cmp можно так легко удалить и заменить его на sign! Вы никогда не реализовывали класс с помощью метода __cmp__? Вы никогда не вызывали cmp и не указывали пользовательскую функцию компаратора?

В общем, мне тоже захотелось использовать функцию sign, но copysign с первым аргументом 1 сработает просто отлично. Я не согласен с тем, что sign был бы более полезен, чем copysign, так как я показал, что это всего лишь подмножество той же самой функции.

.
208
ответ дан 23 November 2019 в 04:19
поделиться

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

-6
ответ дан 23 November 2019 в 04:19
поделиться

"копирайтинг" определен IEEE 754, и является частью спецификации C99. Вот почему он на Пайтоне. Функция не может быть полностью реализована абс(x) * sign(y) из-за того, как она должна обрабатывать значения NaN.

>>> import math
>>> math.copysign(1, float("nan"))
1.0
>>> math.copysign(1, float("-nan"))
-1.0
>>> math.copysign(float("nan"), 1)
nan
>>> math.copysign(float("nan"), -1)
nan
>>> float("nan") * -1
nan
>>> float("nan") * 1
nan
>>> 

Это делает copysign() более полезной функцией, чем sign().

Что касается конкретных причин, почему IEEE signbit(x) недоступен на стандартном Python, то я не знаю. Я могу делать предположения, но это было бы догадкой.

Модуль математики сам использует signbit(1, x) как способ проверки, является ли x отрицательным или неотрицательным. Для большинства случаев, когда речь идет о математических функциях, это кажется более полезным, чем иметь знак(x), который возвращает 1, 0 или -1, потому что на один случай меньше. Например, из математического модуля Python:

static double
m_atan2(double y, double x)
{
        if (Py_IS_NAN(x) || Py_IS_NAN(y))
                return Py_NAN;
        if (Py_IS_INFINITY(y)) {
                if (Py_IS_INFINITY(x)) {
                        if (copysign(1., x) == 1.)
                                /* atan2(+-inf, +inf) == +-pi/4 */
                                return copysign(0.25*Py_MATH_PI, y);
                        else
                                /* atan2(+-inf, -inf) == +-pi*3/4 */
                                return copysign(0.75*Py_MATH_PI, y);
                }
                /* atan2(+-inf, x) == +-pi/2 for finite x */
                return copysign(0.5*Py_MATH_PI, y);

Там ясно видно, что copysign() является более эффективной функцией, чем трехзначная функция sign().

Вы написали:

Если бы я был питоновым дизайнером, я был бы наоборот: не cmp(), а sign()

Это означает, что вы не знаете, что cmp() используется для вещей, кроме чисел. cmp("This", "That") не может быть реализован с помощью функции sign().

Редактирование для сопоставления моих дополнительных ответов в других местах:

Вы основываете свои оправдания на том, как abs() и sign() часто встречаются вместе. Так как стандартная библиотека Си не содержит функции 'sign(x)' любого рода, я не знаю, как вы обосновываете свои взгляды. Есть abs(int) и fabs(double) и fabsf(float) и fabsl(long), но нет упоминания знака. Есть "copysign()" и "signbit()", но они применимы только к числам IEEE 754.

С комплексными числами, что бы sign(-3+4j) возвращала на Python, если бы это было реализовано? abs(-3+4j) возвращает 5.0. Это наглядный пример того, как abs() может быть использована в местах, где знак() не имеет смысла.

Предположим, знак(x) был добавлен на Python, как дополнение к abs(x). Если 'x' является экземпляром пользовательского класса, который реализует метод __abs__(self), то abs(x) вызовет x.__abs__(). Для корректной работы, чтобы работать с abs(x) таким же образом, Python должен получить слот со знаком (x).

Это избыточно для относительно ненужной функции. Кроме того, почему должен существовать знак(x), а отрицательный(x) и отрицательный(x) не должны существовать? Мой отрывок из реализации математического модуля Python показывает, как copybit(x, y) может быть использован для реализации nonnegative(), чего не может сделать простой знак(x).

Python должен поддерживать лучшую поддержку математической функции IEEE 754/C99. Это добавит функцию signbit(x), которая будет делать то, что вы хотите в случае с плавающими точками. Она не будет работать для целых или сложных чисел, тем более для строк, и не будет иметь того имени, которое вы ищете.

Вы спрашиваете "почему", а ответ: "Знак(x) не полезен". Вы утверждаете, что это полезно. Тем не менее, ваши комментарии показывают, что вы не знаете достаточно, чтобы сделать это утверждение, что означает, что вы должны будете показать убедительные доказательства его необходимости. Говорить, что NumPy реализует его недостаточно убедительно. Нужно показать примеры того, как существующий код будет улучшен с помощью знаковой функции.

И что это выходит за рамки StackOverflow. Возьмите его вместо этого в один из списков Python

.
56
ответ дан 23 November 2019 в 04:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: