__add__ method and negative numbers in Python - python

I always though that using the "+" operator in Python (3.5) calls the __add__ method under the hood and return the sum. However, I noticed some quirky behavior when negative numbers are involved.
Naturally,
>>>-3 + 7
returns 4
But(!)
>>>-3 .__add__(7)
returns -10 and
>>>-3 .__add__(-7)
4
>>>3 .__add__(7)
10
Is there a reason why __add__ signs the arguments if the object is signed. Also, what changes in the method so that when I use "+", the "correct" value comes out?

- is an operator too, an unary one. You called __add__ on 3, not on the result of - applied to 3, because attribute access binds more tightly than the - operator.
Use parentheses:
>>> (-3).__add__(7)
4
Your code applies the - unary operator to the result of 3 + 7 instead.

.__add__ is an operation between two objects so 3.add(7) = 10;
-3.add(7) is like calling add for 3 and 7 and then applying (-) as an operator
So -(10) as a result
You need to use parentheses to get the proper operation

Related

Unexpected outcome for negation of True and False using ~ [duplicate]

What's the usage of the tilde operator in Python?
One thing I can think about is do something in both sides of a string or list, such as check if a string is palindromic or not:
def is_palindromic(s):
return all(s[i] == s[~i] for i in range(len(s) / 2))
Any other good usage?
It is a unary operator (taking a single argument) that is borrowed from C, where all data types are just different ways of interpreting bytes. It is the "invert" or "complement" operation, in which all the bits of the input data are reversed.
In Python, for integers, the bits of the twos-complement representation of the integer are reversed (as in b <- b XOR 1 for each individual bit), and the result interpreted again as a twos-complement integer. So for integers, ~x is equivalent to (-x) - 1.
The reified form of the ~ operator is provided as operator.invert. To support this operator in your own class, give it an __invert__(self) method.
>>> import operator
>>> class Foo:
... def __invert__(self):
... print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert
Any class in which it is meaningful to have a "complement" or "inverse" of an instance that is also an instance of the same class is a possible candidate for the invert operator. However, operator overloading can lead to confusion if misused, so be sure that it really makes sense to do so before supplying an __invert__ method to your class. (Note that byte-strings [ex: '\xff'] do not support this operator, even though it is meaningful to invert all the bits of a byte-string.)
~ is the bitwise complement operator in python which essentially calculates -x - 1
So a table would look like
i ~i
-----
0 -1
1 -2
2 -3
3 -4
4 -5
5 -6
So for i = 0 it would compare s[0] with s[len(s) - 1], for i = 1, s[1] with s[len(s) - 2].
As for your other question, this can be useful for a range of bitwise hacks.
One should note that in the case of array indexing, array[~i] amounts to reversed_array[i]. It can be seen as indexing starting from the end of the array:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
^ ^
i ~i
Besides being a bitwise complement operator, ~ can also help revert a boolean value, though it is not the conventional bool type here, rather you should use numpy.bool_.
This is explained in,
import numpy as np
assert ~np.True_ == np.False_
Reversing logical value can be useful sometimes, e.g., below ~ operator is used to cleanse your dataset and return you a column without NaN.
from numpy import NaN
import pandas as pd
matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]
The only time I've ever used this in practice is with numpy/pandas. For example, with the .isin() dataframe method.
In the docs they show this basic example
>>> df.isin([0, 2])
num_legs num_wings
falcon True True
dog False True
But what if instead you wanted all the rows not in [0, 2]?
>>> ~df.isin([0, 2])
num_legs num_wings
falcon False False
dog True False
I was solving this leetcode problem and I came across this beautiful solution by a user named Zitao Wang.
The problem goes like this for each element in the given array find the product of all the remaining numbers without making use of divison and in O(n) time
The standard solution is:
Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
and then multiplying them for the final answer
His solution uses only one for loop by making use of. He computes the left product and right product on the fly using ~
def productExceptSelf(self, nums):
res = [1]*len(nums)
lprod = 1
rprod = 1
for i in range(len(nums)):
res[i] *= lprod
lprod *= nums[i]
res[~i] *= rprod
rprod *= nums[~i]
return res
Explaining why -x -1 is correct in general (for integers)
Sometimes (example), people are surprised by the mathematical behaviour of the ~ operator. They might reason, for example, that rather than evaluating to -19, the result of ~18 should be 13 (since bin(18) gives '0b10010', inverting the bits would give '0b01101' which represents 13 - right?). Or perhaps they might expect 237 (treating the input as signed 8-bit quantity), or some other positive value corresponding to larger integer sizes (such as the machine word size).
Note, here, that the signed interpretation of the bits 11101101 (which, treated as unsigned, give 237) is... -19. The same will happen for larger numbers of bits. In fact, as long as we use at least 6 bits, and treating the result as signed, we get the same answer: -19.
The mathematical rule - negate, and then subtract one - holds for all inputs, as long as we use enough bits, and treat the result as signed.
And, this being Python, conceptually numbers use an arbitrary number of bits. The implementation will allocate more space automatically, according to what is necessary to represent the number. (For example, if the value would "fit" in one machine word, then only one is used; the data type abstracts the process of sign-extending the number out to infinity.) It also does not have any separate unsigned-integer type; integers simply are signed in Python. (After all, since we aren't in control of the amount of memory used anyway, what's the point in denying access to negative values?)
This breaks intuition for a lot of people coming from a C environment, in which it's arguably best practice to use only unsigned types for bit manipulation and then apply 2s-complement interpretation later (and only if appropriate; if a value is being treated as a group of "flags", then a signed interpretation is unlikely to make sense). Python's implementation of ~, however, is consistent with its other design choices.
How to force unsigned behaviour
If we wanted to get 13, 237 or anything else like that from inverting the bits of 18, we would need some external mechanism to specify how many bits to invert. (Again, 18 conceptually has arbitrarily many leading 0s in its binary representation in an arbitrary number of bits; inverting them would result in something with leading 1s; and interpreting that in 2s complement would give a negative result.)
The simplest approach is to simply mask off those arbitrarily-many bits. To get 13 from inverting 18, we want 5 bits, so we mask with 0b11111, i.e., 31. More generally (and giving the same interface for the original behaviour):
def invert(value, bits=None):
result = ~value
return result if bits is None else (result & ((1 << bits) - 1))
Another way, per Andrew Jenkins' answer at the linked example question, is to XOR directly with the mask. Interestingly enough, we can use XOR to handle the default, arbitrary-precision case. We simply use an arbitrary-sized mask, i.e. an integer that conceptually has an arbitrary number of 1 bits in its binary representation - i.e., -1. Thus:
def invert(value, bits=None):
return value ^ (-1 if bits is None else ((1 << bits) - 1))
However, using XOR like this will give strange results for a negative value - because all those arbitrarily-many set bits "before" (in more-significant positions) the XOR mask weren't cleared:
>>> invert(-19, 5) # notice the result is equal to 18 - 32
-14
it's called Binary One’s Complement (~)
It returns the one’s complement of a number’s binary. It flips the bits. Binary for 2 is 00000010. Its one’s complement is 11111101.
This is binary for -3. So, this results in -3. Similarly, ~1 results in -2.
~-3
Output : 2
Again, one’s complement of -3 is 2.
This is minor usage is tilde...
def split_train_test_by_id(data, test_ratio, id_column):
ids = data[id_column]
in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))
return data.loc[~in_test_set], data.loc[in_test_set]
the code above is from "Hands On Machine Learning"
you use tilde (~ sign) as alternative to - sign index marker
just like you use minus - is for integer index
ex)
array = [1,2,3,4,5,6]
print(array[-1])
is the samething as
print(array[~1])

Using AND inside abs(number) in Python

Trying to understand how AND statement works inside abs(numbers) function.
Calling print(abs(21-22 and 9-4 and 11-8))
This would always give me whatever the last expression is. In this case it calculates 11-8, so it prints 3.
Why other expressions are not in the output and no error as well?
The fact that the expression is inside an abs call doesn't change the way that it's interpreted:
>>> 21-22 and 9-4 and 11-8
3
which is of course the same as:
>>> -1 and 5 and 3
3
An and evaluates the "truthiness" of each operand. If either of them is "falsey", that one is returned; otherwise the last one is returned.
All int values except 0 are "truthy", so the only time you'll get something other than the last value from an and of ints is if one of them is zero:
>>> -1 and 0 and 3
0
and is a logical operator, it will return True if both the operands of the operator are true. I believe the comma does what you expected to do in this case:
print(abs(21-22),abs(9-4),abs(11-8))

What is `operator.__inv__` existing for?

What is the difference with inv and invert?
>>> import operator
>>> operator.inv is operator.invert
False
>>> operator.__inv__ is operator.__invert__
False
I gather that __invert__ is the hook for the unary ops like ~1 or (1).__invert__().
But what is the other one __inv__ corresponding to? Or if it's same, why we have another name and a different function added for doing same thing?
Both represent the same operator. The long spelling was added in Python 2.0, and the short spelling was never removed.
operator.inv(obj)
operator.invert(obj)
operator.__inv__(obj)
operator.__invert__(obj)
Return the bitwise inverse of the number obj.
This is equivalent to ~obj.
New in version 2.0: The names invert() and __invert__().
Source: Python 2 operator documentation.
These are implemented as different objects because their representation reflects the name. Note that the corresponding dunder and regular names do share the same representation and object.
>>> operator.__inv__
<built-in function inv>
>>> operator.__invert__
<built-in function invert>
>>> operator.__inv__ is operator.inv
True
>>> operator.__invert__ is operator.invert
True
Historically, both names were equally viable - the Python 1 operator module used the inv/__inv__ name, whereas the Python 1 data model used the special method __invert__ name.

Order of operation for **

I want to know why does the following happen.
The code below evaluates right side 1**3 first then 2**1
2**1**3 has the value of 2
However, for the below code left side 7//3 is evaluated first then 2*3. Finally 1+6-1=6.
1+7//3*3-1 has the value of 6
Take a look at the documentation of operator precedence. Although multiplication * and floor division // have the same precedence, you should take note of this part:
Operators in the same box group left to right (except for exponentiation, which groups from right to left).
For the convention of 213 being evaluated right-associative, see cross-site dupe on the math stackexchange site: What is the order when doing xyz and why?
The TL;DR is this: since the left-associative version (xy)z would just equal xy*z, it's not useful to have another (worse) notation for the same thing, so exponentiation should be right associative.
Almost all operators in Python (that share the same precedence) have left-to-right associativity. For example:
1 / 2 / 3 ≡ (1 / 2) / 3
One exception is the exponent operator which is right-to-left associativity:
2 ** 3 ** 4 ≡ 2 ** (3 ** 4)
That's just the way the language is defined, matching mathematical notation where abc ≡ a(bc).
If it were (ab)c, that would just be abc.
Per Operator Precedence, the operator is right associative: a**b**c**d == a**(b**(c**d)).
So, if you do this:
a,b,c,d = 2,3,5,7
a**b**c**d == a**(b**(c**d))
you should get true after a looooong time.
The Exponent operator in python has a Right to Left precedence. That is out of all the occurrences in an expression the calculation will be done from Rightmost to Leftmost. The exponent operator is an exception among all the other operators as most of them follow a Left to Right associativity rule.
2**1**3 = 2
The expression
1+7//3*3-1
It is a simple case of Left to Right associativity. As // and * operator share the same precedence, Associativity(one is the Left) is taken into account.
This is just how math typically works
213
This is the same as the first expression you used. To evaluate this with math, you'd work your way down, so 13=1 and then 21 which equals 2.
You can make sense of this just by thinking about the classic PEMDAS (or Please Excuse My Dear Aunt Sally) order of operations from mathematics. In your first one, 2**1**3 is equivalent to , which is really read as . Looking at it this way, you see that you do parenthesis (P) first (the 1**3).
In the second one, 1+7//3*3-1 == 6 you have to note that the MD and AS of PEMDAS are actually done in order of whichever comes first reading from left-to-right. It's simply a fault of language that we have to write one letter before another (that is, we could write this as PEDMAS and it still be correct if we treat the D and M appropriately).
All that to say, Python is treating the math exactly the same way as we should even if this were written with pen and paper.

what is the meaning of float.__pos__? [duplicate]

This question already has answers here:
What's the purpose of the + (pos) unary operator in Python?
(7 answers)
Closed 8 years ago.
I am writing a function computing like eval. When I come to float.__pos__ ,I really don't Know why there exists such a useless function. Because:
>>> float.__pos__(-1.0)
-1.0
>>> float.__pos__(1.0)
1.0
while float.__neg__ is totally different:
>>> float.__neg__(1.0)
-1.0
So what is the meaning of float.__pos__?
>>> help(float.__pos__)
Help on wrapper_descriptor:
__pos__(...)
x.__pos__() <==> +x
It's the "unary plus" operator, invoked when you do +x with x a float. It basically does nothing for floats, as you've discovered ;-) However, you could define a subclass that did something non-trivial with it. That's why it's there.
The __pos__ method defines the effect of the unary + operator for any object.
As Tim Peters mentions, it has no effect for floats.
See What's the purpose of the + (pos) unary operator in Python? for an example where it's used to do something.
Python has a unary negation operator to negate numbers, as you're probably well aware:
>>> x = 5
>>> print(-x)
-5
>>> x = -5
>>> print(-x)
5
Say you're making a list of numbers, though. It might be more consistent if you prefixed the positive ones with a +, so Python has a unary + operator, too:
>>> numbers = [-3, -2, -1, 0, +1, +2, +3]
When you use the unary + operator on a number, you're right that it doesn't do anything; it's there just for consistency.
Now when you consider that in Python you can override operators on types, of course you'd need a __neg__ to negate an instance of that type. Python just decided to be consistent by also having a __pos__ to…not negate an instance of that type. float, like all other types overriding these operators, follow this protocol, and float's implementation of __pos__ is just the identity function.

Categories

Resources