Davide - 8 months ago 26

Python Question

I can't understand why Python doesn't have a

`sign`

`abs`

`sign`

`sign`

In python 2.6 there is even a

`copysign`

`copysign(x,y)`

`sign`

`copysign`

`abs(x) * sign(y)`

Obviously

`sign(x)`

`cmp(x,0)`

If I were a python designer, I would been the other way arond: no

`cmp`

`sign`

`cmp(x,y)`

`sign(x-y)`

`sorted`

`x>y`

`cmp`

`cmp`

So, the question is: why did the Python designer(s) decide to leave the

`sign`

`copysign`

`sign`

Am I missing something?

EDIT - after Peter Hansen comment.

Fair enough that you didn't use it, but you didn't say what you use python for. In 7 years that I use python, I needed it countless times, and the last is the straw that broke the camel's back!

Yes, you can pass cmp around, but 90% of the times that I needed to pass it was in an idiom like

`lambda x,y: cmp(score(x),score(y))`

Finally, I hope you agree that

`sign`

`copysign`

Answer

**EDIT:**

Indeed there was a patch which included `sign()`

in math, but it wasn't accepted, because they didn't agree on what it should return in all the edge cases (+/-0, +/-nan, etc)

So they decided to implement only copysign, which (although more verbose) can be used to delegate to the end user the desired behavior for edge cases - which sometimes might require the call to `cmp(x,0)`

.

I don't know why it's not a built-in, but I have some thoughts.

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

Most importantly, `copysign`

is a superset of `sign`

! Calling `copysign`

with x=1 is the same as a `sign`

function. So you could just use `copysign`

and *forget about it*.

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

If you get sick of passing two whole arguments, you can implement `sign`

this way, and it will still be compatible with the IEEE stuff mentioned by others:

```
>>> 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
```

Secondly, usually when you want the sign of something, you just end up multiplying it with another value. And of course that's basically what `copysign`

does.

So, instead of:

```
s = sign(a)
b = b * s
```

You can just do:

```
b = copysign(b, a)
```

And yes, I'm surprised you've been using Python for 7 years and think `cmp`

could be so easily removed and replaced by `sign`

! Have you never implemented a class with a `__cmp__`

method? Have you never called `cmp`

and specified a custom comparator function?

In summary, I've found myself wanting a `sign`

function too, but `copysign`

with the first argument being 1 will work just fine. I disagree that `sign`

would be more useful than `copysign`

, as I've shown that it's merely a subset of the same functionality.