How do I make different variables refer to the same value, but still allow operations directly?
What is a good way to make different variables equal to the same value while still keeping direct operations like eg. *
by value?
An example of the desired code could do something like:
a = <Reference to integer 2>
b = a
print(a * b) # Should show 4
<a update (not with assign using =) with reference to integer 3>
print(a * b) # Should show 9
A less desirable solution is to use a container for the value like namespace, list, dict, etc., but this requires a reference to the type attribute .value
below, so it is less desirable:
import types
a = types.SimpleNamespace(value = 2)
b = a
print(a.value * b.value) # Should show 4
a.value = 3
print(a.value * b.value) # Should show 9
What is a good way to encapsulate the value, so direct operations are possible?
source to share
You can create a class that overrides the multiplication operation.
class Reference:
def __init__(self, value):
self.value = value
def __mul__(self, other):
return Reference(self.value * other.value)
This will allow you to immediately multiply links to each other. For example, Reference(3) * Reference(4)
creates Reference(12)
.
You probably want to override __rmul__
all other numeric operations as well. Abstract classes numbers
can be helpful so you don't forget.
source to share
Your desired behavior can be modeled with a class, albeit a little clunky and inefficient:
class reference:
def __init__(self, num): self.num = num
def get(self): return self.num
def set(self, num): self.num = num
def __mul__(self, other): return self.num * other
def __div__(self, other): return self.num / other
def __add__(self, other): return self.num + other
def __sub__(self, other): return self.num - other
When overloading these operators, the following:
a = reference(5) b = a print a.get() print a * 4
prints
5 20
I realize this is quite cumbersome if you want to refer to different types, since you will have to overload the operators you need for each type, but AFAIK this is the closest thing to simulating pointers.
Alternatively, you can only include get
, set
and __init__
in your class reference
and then add the required overloading functions:
class reference:
def __init__(self, num): self.num = num
def get(self): return self.num
def set(self, num): self.num = num
a = reference(5)
reference.__mul__ = lambda self, num: self.num * num
print a * 4
The above prints 20
source to share
class Manager:
def __init__(self,data):
self.__dict__["data"] = data
def __getattr__(self,attr):
return getattr(self.data,attr)
def __setattr__(self,attr,val):
return setattr(self.data,attr,val)
def set(self,val):
self.__dict__["data"] = val
master = Manager(55)
print print master+5
print slave = master
print slave.set(88)
print slave + 10
print master+2
...
master_s = Manager("Test")
print master_s + " String"
...
master_c = Manager(MyCustomClass())
master_c.do_my_method()
may be?
source to share
To use container classes, but still allow direct operations, you can overload the operators you want to use for that type. As an example, let's define a class SharedInt
and write an overload for an operator *
that takes two SharedInt
as arguments.
__mul__(self, other):
return self.value * other.value
source to share