1

My question comes from this page, while I would like to create a pointer(-like thing) for an list element. The element is a primitive value (string) so I have to create a FooWrapper class as that page says.

I know that by setting __repr__ one can directly access this value.

class FooWrapper(object):
    def __init__(self, value):
         self.value = value
    def __repr__(self):
         return repr(self.value)


>>> bar=FooWrapper('ABC')
>>> bar
'ABC'
>>> bar=FooWrapper(3)
>>> bar
3

Now I can use it as an reference of string:

>>> L=[3,5,6,9]
>>> L[1]=FooWrapper('ABC')
>>> L
[3,'ABC',6,9]
>>> this=L[1]
>>> this.value='BCD'
>>> print(L)
[3,'BCD',6,9]

So now I have a pointer-like this for the list element L[1].

However it is still inconvenient since I must use this.value='BCD' to change its value. While there exists a __repr__ method to make this directly return this.value, is there any similar method to make this='BCD' to do this.value='BCD' ? I know this changes the rule of binding.. but anyway, is it possible?

I would also appreciate if there is a better solution for a list element pointer.

Thank you in advance:)

Ruixing Wang
  • 75
  • 1
  • 7

3 Answers3

2

I'm not sure exactly what you are trying to do, but you could do something like:

class FooWrapper(object):
    def __init__(self, value):
         self.value = value
    def __repr__(self):
         return 'FooWrapper(' + repr(self.value) + ')'
    def __str__(self):
        return str(self.value)
    def __call__(self,value):
        self.value = value

Here I got rid of your idea of using __repr__ to hide FooWrapper since I think it a bad idea to hide from the programmer what is happening at the REPL. Instead -- I used __str__ so that when you print the object you will print the wrapped value. The __call__ functions as a default method, which doesn't change the meaning of = but is sort of what you want:

>>> vals = [1,2,3]
>>> vals[1] = FooWrapper("Bob")
>>> vals
[1, FooWrapper('Bob'), 3]
>>> for x in vals: print(x)

1
Bob
3
>>> this = vals[1]
>>> this(10)
>>> vals
[1, FooWrapper(10), 3]

However, I think it misleading to refer to this as a pointer. It is just a wrapper object, and is almost certain to make dealing with the wrapped object inconvenient.

On Edit: The following is more of a pointer to a list. It allows you to create something like a pointer object with __call__ used to dereference the pointer (when no argument is passed to it) or to mutate the list (when a value is passed to __call__). It also implements a form of p++ called (pp) with wrap-around (though the wrap-around part could of course be dropped):

class ListPointer(object):
    def __init__(self, myList,i=0):
         self.myList = myList
         self.i = i % len(self.myList)

    def __repr__(self):
         return 'ListPointer(' + repr(self.myList) + ',' + str(self.i) + ')'

    def __str__(self):
        return str(self.myList[self.i])

    def __call__(self,*value):
        if len(value) == 0:
            return self.myList[self.i]
        else:
            self.myList[self.i] = value[0]

    def pp(self):
        self.i = (self.i + 1) % len(self.myList)

Used like this:

>>> vals = ['a','b','c']
>>> this = ListPointer(vals)
>>> this()
'a'
>>> this('d')
>>> vals
['d', 'b', 'c']
>>> this.pp()
>>> this()
'b'
>>> print(this)
b

I think that this is a more transparent way of getting something which acts like a list pointer. It doesn't require the thing pointed to to be wrapped in anything.

John Coleman
  • 51,337
  • 7
  • 54
  • 119
0

The __repr__ method can get a string however it wants to. Let's say it says return repr(self.value) + 'here'. If you say this = '4here', what should be affected? Should self.value be assigned to 4 or 4here? What if this had another attribute called key and __repr__ did return repr(self.key) + repr(self.value)? When you did this = '4here', would it assign self.key to the whole string, assign self.value to the whole string, or assign self.key to 4 and self.value to here? What if the string is completely made up by the method? If it says return 'here', what should this = '4here' do?

In short, you can't.

zondo
  • 19,901
  • 8
  • 44
  • 83
0

Self-Answer based on John Coleman's idea:

class ListPointer(object):
    def __init__(self,list,index):
          self.value=list[index]
          list[index]=self
    def __repr__(self):
          return self.value
    def __call__(self,value):
          self.value=value

>>> foo=[2,3,4,5]
>>> this=ListPointer(foo,2)
>>> this
4
>>> foo
[2,3,4,5]
>>> this('ABC')
>>> foo
[2,3,'ABC',5]
>>> type(foo(2))
<class '__main__.ListPointer'>

ListPointer object accepts a list and an index, stores the list[index] in self.value and then substitutes the list element with self. Similarly a pp method can also be achieved, while the former element should be restored and the next element be substituted with self object. By directly referring foo[2] one also gets this object, which is what I want. (Perhaps this should be called as a reference rather than a pointer..)

Ruixing Wang
  • 75
  • 1
  • 7