Just to add on to an excellent existing answer, but this doesn't work because you are modifying the class instance, and not the class.
In order to get the behavior you desire, you can modify the class during __init__
, however, this is woefully inadequate (since it modifies the class, and therefore all instances of the class), and you are better off making those changes visible at the class scope.
For example, the following are equivalent:
class SpecialInteger1:
def __init__(self,x):
self.x = x
self.__class__.__eq__ = self.equals_normal
...
class SpecialInteger2:
def __init__(self,x):
self.x = x
def equals_normal(self,other):
return self.x == other.x
def __eq__(self, other):
return self.equals_normal(other)
You should prefer case SpecialInteger2
in all examples, since it is more explicit about what it does.
However, none of this actually solves the issue you are trying to solve: how can I create a specialized equality comparison at the instance level that I can toggle? The answer is through the use of an enum (in Python 3):
from enum import Enum
class Equality(Enum):
NORMAL = 1
SPECIAL = 2
class SpecialInteger:
def __init__(self, x, eq = Equality.NORMAL):
self.x = x
self.eq = eq
def equals_normal(self, other):
return self.x == other.x
def equals_special(self, other):
return self.x != other.x
def __eq__(self, other):
return self.__comp[self.eq](self, other)
# Define a dictionary for O(1) access
# to call the right method.
__comp = {
Equality.NORMAL: equals_normal,
Equality.SPECIAL: equals_special
}
Let's walk through this quickly, since there are 3 parts:
- An instance member variable of
eq
, which can be modified dynamically.
- An implementation of
__eq__
that selects the correct equality function based on the value of self.eq
.
- A namespace-mangled dictionary (a class/member variable that starts with
__
, in this case, self.__comp
) that allows efficient lookup of the desired equality method.
The dictionary can easily be done-away with, especially for cases where you only wish to support 1-5 different possible comparisons, and replaced with idiomatic if/then
statements, however, if you ever wish to support many more comparison options (say, 300), a dictionary will be much more efficient O(1)
than if/then comparisons (linear search, O(n)
).
If you wish to do this with setters (like in the original example), and actually hide the member functions from the user, you can also do this by directly storing the function as a variable.