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?

+3


source to share


5 answers


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.

+5


source


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

+2


source


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?

+1


source


You can use a list around the object:

>>> a = [2]
>>> b = a
>>> print(a[0]*b[0])
4 
>>> a[0]+=1
>>> print(a[0]*b[0])
9

      

0


source


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

      

0


source







All Articles