1

I want to create a Python class that can:

  • Take a variable as an argument when instantiating
  • Store the value of the variable in an attribute
  • Store the current value of the variable whenever "update()" method is used.

The code below did not work as intended. How can I update the value of the attribute through a method call, keeping in mind that it must work for arbitrary variables?

class MyObject():
    def __init__(self,data): 
        self.data = data 

    def update(self):
        self.data = data

value = 0

dataobject = MyObject(value)

value = 1

dataobject.update() #NameError: name 'data' is not defined
jarlemag
  • 171
  • 1
  • 5
  • 1
    That's just not how Python works ... pass the value into the update function. – wim Nov 21 '20 at 02:01
  • 2
    Does this answer your question? [How do I pass a variable by reference?](https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – joshmeranda Nov 21 '20 at 02:01
  • you then need to create a class with only the value as member, integers are immutable, and do not have a handle/id – rioV8 Nov 21 '20 at 02:04
  • 1
    You cannot really emulate pass by reference, as you want. In Python, references to objects are passed in, so you can mutate that object and the effect is visible in the caller. – juanpa.arrivillaga Nov 21 '20 at 02:07
  • @rioV8 Ints do have an ID. Maybe you meant a different term? For example `id(0)` -> 140736127440512 on my interpreter. – wjandrea Nov 21 '20 at 02:11
  • @puffin : "If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like a list." Putting the variable in a list seems to work. Thanks for the link. – jarlemag Nov 21 '20 at 02:32
  • @wjandrea maybe I mix languages and simple type implementations – rioV8 Nov 21 '20 at 02:33

1 Answers1

1

Pass by reference doesn't work the way you want in Python for int and other basic types (different story for lists and other types of objects, but I'll just answer the question you asked).

I don't really recommend this approach, but you could do this with the Global keyword:

class MyObject():
    def __init__(self,data):
        self.data = data

    def update(self):
        global value         # only change is this
        self.data = value

value = 0

dataobject = MyObject(value)

value = 1

dataobject.update()

print(dataobject.data)  # prints 1

objects in Python don't have private attributes, so you could directly set the value:

dataobject.data = 1

Neither of these strike me as best practices, but I would have to know more about what you are trying to do in order to give you the best advice. Note that if you plan on having a bunch of instances of MyObject, trying to sync them up with a single global value may get out of hand. I would advise a new question with more info about what you are trying to do and someone will give the the best approach.

TSeymour
  • 729
  • 3
  • 17
  • 1
    I already considered "Global", but that won't let me work with arbitrary variables as the argument. For the same reason, I can't set the value directly. The use of the class is to represent an UI element to display arbitrary data, which needs to be kept up to date. (As a subclass of the Sprite class in pygame, to be exact. The update() method is called every frame for all Sprite objects). – jarlemag Nov 21 '20 at 02:11
  • The question got closed so I can't add it as an answer, but I solved it for now (I think) by using a list as the argument: `class MyObject(): def __init__(self,data): self.myref = data self.data = self.myref[0] def update(self): self.data = self.myref[0]` – jarlemag Nov 21 '20 at 02:25
  • this will not work if `val2 = 5; do2 = MyObject(val2); val2 = 10; do2.update()` – rioV8 Nov 21 '20 at 02:29
  • @riov8: The code here seems to work fine: https://pastebin.com/5iBJzNJV Do you see anything wrong with it? (Or maybe I misunderstood you. Not sure if you referred to the code in the answer or in my question). – jarlemag Nov 21 '20 at 02:37
  • 1
    @jarlemag I refer to the solution from TSeymour, better if you implement a class that has the `__set__` operator implemented, https://python-reference.readthedocs.io/en/latest/docs/dunderdsc/get.html – rioV8 Nov 21 '20 at 02:45