Manipulating Python Magic Methods
Manipulating Python Magic Methods
I have more of a background with data science libraries or calling methods and attributes from classes. I am experimenting with manipulating magic methods. I am having a difficult time getting bool types and returning their opposites.
bool
I did something with str and datetime objects that worked but can't seem to to the same with __cmp__, __lt__, __eq__ or `gt'. Here is my code:
str
datetime
__cmp__
__lt__
__eq__
class Opposite:
def __cmp__(self, other):
if other.__class__.__name__ == 'bool':
return other
def __lt__(self, other):
if other.__class__.__name__ == 'bool':
return other
def __eq__(self, other):
if other.__class__.__name__ == 'bool':
return other
def __gt__(self, other):
if other.__class__.__name__ == 'bool':
return other
if __name__=="__main__":
""" test class Compare """
a = 1
b = 1
c = a < b
d = a > b
e = a == b
print("Results:natnbtnctndtnetn".format(a,b,c,d,e))
print("nType:na-typetnb-typetnc-typetnd-typetne-typetn"
.format(type(a),type(b),type(c),type(d),type(e)))
This prints the following:
Results:
a 1
b 1
c False
d False
e True
Type:
a-type <class 'int'>
b-type <class 'int'>
c-type <class 'bool'>
d-type <class 'bool'>
e-type <class 'bool'>
As you can see, the results are the same as not using the class at all. I added an __init__ method to print using Opposite and it only prints that if I instantiate the object with something like a = Opposite().
__init__
using Opposite
a = Opposite()
I would like to enter something like a > b, a < b, or a == b, and return the opposite boolean value, True, or False, as an exercise.
a > b
a < b
a == b
True
False
I tried several things such as placing the methods under the __init__ method I created, which didn't work either. I read on this and still don't quite understand how to do this with booleans, integers and floats for that matter. The way the methods are above is how I was able to turn datetime objects into strings with __add__, __radd__ and __rsub__ methods.
__init__
__add__
__radd__
__rsub__
Thank you for your help.
EDIT
Thanks to your help, I have a better understanding and have completed my small experiment with this code:
class Opposite:
def __init__(self, x):
self._x = x
def __lt__(self, other):
return not self._x < other._x
def __eq__(self, other):
return not self._x == other._x
def __gt__(self, other):
return not self._x > other._x
def __le__(self, other):
return not self._x <= other._x
def __ge__(self, other):
return not self._x >= other._x
def tester(w, x, y, z):
try:
# Original values
a = w < x
b = w > x
c = w == x
d = w <= x
e = w >= x
# Opposite values
f = y < z
g = y > z
h = y == z
i = y <= z
j = y >= z
# Results
k = 'Fail' if a == f else 'Success'
l = 'Fail' if b == g else 'Success'
m = 'Fail' if c == h else 'Success'
n = 'Fail' if d == i else 'Success'
o = 'Fail' if e == j else 'Success'
print('nComparing and :t<t>t==t<=t>='.format(w, x))
print('Original Values:', end='t')
print('0t1t2t3t4'.format(a, b, c, d, e))
print('Opposite Values:', end='t')
print('0t1t2t3t4'.format(f, g, h, i, j))
print('Comparisons:', end='t')
print('t0t1t2t3t4'.format(k, l, m, n, o))
except(Exception) as err:
print(err)
if __name__=="__main__":
""" test class Compare """
a = 1
b = 2
c = Opposite(a)
d = Opposite(b)
tester(a, b, c, d)
This prints the following:
Comparing 1 and 2: < > == <= >=
Original Values: True False False True False
Opposite Values: False True True False True
Comparisons: Success Success Success Success Success
Opposite
__cmp__
For your class methods to be used the left operand has to be an instance of that class. Yours is an
int.– Klaus D.
Aug 25 at 1:09
int
@KlausD.: Technically, it can work if the right operand is an instance of the class, and the left operand has a correctly implemented comparator (one that returns
NotImplemented when it doesn't know how to compare itself to the right operand); in that case, the left operand is tried, and when it returns NotImplemented, the reflected operand is tried for the right hand side (see final paragraph of linked section). Of course, in the OP's case, nothing is an instance of the class at all.– ShadowRanger
Aug 25 at 1:32
NotImplemented
NotImplemented
That is correct, but does not apply to his class and an int.
– Klaus D.
Aug 25 at 1:55
Originally, I was hoping to manipulate say
__lt__ so I can simply perform 2 < 1 and get True without instantiating the class, but that isn't how it works. I would have to break python to do that lol– Debug255
Aug 30 at 19:47
__lt__
2 < 1
True
1 Answer
1
If you mean that you want to return the negation of the boolean resulting from the comparison you could do something like
class T:
def __init__(self, x):
self._x = x
def __lt__(self, other):
return not self._x < other._x
t1 = T(1)
t2 = T(2)
print(t1 < t2) #False
Note that in the comparison self._x < other._x you are using the __lt__ method of the int class.
self._x < other._x
__lt__
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You didn't make any instances of your class at all. Why do you expect your comparison code to execute? You'd need to make instances of
Oppositefor your code to be used (and to be clear, as written it's not the opposite of anything). Also, if this is Python 3,__cmp__isn't magic anymore, only the individual rich comparison methods are used.– ShadowRanger
Aug 25 at 1:09