0

I have a class, and I created two instances of it ,object1 and object2, I addend an attribute to each called "number", I want to be able to choose to which class I apply a function that I have created to change the "number"attribute, I managed to create the function but when i execute it only does it at a local level in the function, it does not return the result to the original object1.number instance, I assumne the problem is in how I positioned my variables.

So i want my global object1.number attribute to be changed inside the number_changer function and then be able to see that change outside the function.

I have used the print function along the code to follow the process, and it seems to do well, just its unable to change the global attribute

class ClassA():    
    pass


object1 = ClassA()    
object1.number = "0"    
object2 = ClassA()    
object2.number = "1"    


current_object = "object1"    
x = input("new number ")    

print(object1.number)    


def number_changer(object_name,new_number):    
    variable = object_name + ".number"    
    global object1    

    ref_obj_list = ["object1.number", "object2.number"]    
    real_obj_list = [object1.number, object2.number]    
    count = -1    
    for item in ref_obj_list:    
        count += 1    
        if variable == item:    
            real_obj_list[count]  = new_number    
            d = real_obj_list[count]    

            return d    




print(number_changer(current_object,x))    

print(object1.number)    

when I put the number "5" in the input the result is this

0    
5    
0    

the object1.number attribute does not change or at least not in a global level

6
  • I'm calling "x/y problem" on this question. What problem are you trying to solve with this indirect code? You manipulate object attributes outside the class. You go out of your way to hard-code an indirect relationship between each object and the name of the variable. You hand-code your own indexing loop. You can bypass virtually all of this with object1.number = input("new number "). Commented Sep 11, 2019 at 20:13
  • @PatrickArtner I want to change the number attribute of my objects, but I will not always know which object I will change the attribute, the purpose of the function is to detect the object an then change it. Commented Sep 11, 2019 at 20:15
  • @Prune I cant do that , because I will not always know the object to be changed, the variable "current_object" will also be an input, that kinda of be generated randomly, thats what the function does, find the object to change the attribute. Commented Sep 11, 2019 at 20:17
  • ... You are only replacing the value inside your local list inside your function with a string - nothing modifies the original ClassA() instances numbers ... Commented Sep 11, 2019 at 20:18
  • 1
    I'm still confused as to the interface design -- you're requiring that the user know all of your internal variable names, a clear violation of interface practices. What problem are you solving with this? Commented Sep 11, 2019 at 20:21

4 Answers 4

2

Most of your code is superflous. If you pass an object to a function and access a non-existing attribute you get an error. If you set an attribute it will create it if not existing or change it if already existing:

class A:
    pass 


a1 = A()
a2 = A()

def changer(o,newtext):
    try:
        o.text = o.text + newtext
    except AttributeError:            # happens if the attribute does not exist
        print(".text does not exist")

a1.text = "whatever"
a2.text = "never"

print(a1.text, a2.text)  # prints whats being set
changer(a1,"changed")    # changes a1.text
print(a1.text, a2.text)  # prints changed text

changer(A(),"hallo")  # prints the caught/handled exception - A() has no .text

Output:

whatever never
whateverchanged never
.text does not exist

The "normal" way to do this would be to simpy add text to the class:

class A:
    def __init__(self):
        self.text = None

that way it exists all the time and is unique to each instance.

See What is the difference between class and instance attributes? for explanation of instance and (shared) class attributes


To select an object by user input, use a dictionary:

myAs = {"A1":a1, "A2":a2}   # a1,a2 from above

print(a1.text, a2.text)    
whichOne = input("Which element to change? " +  repr(list(myAs.keys())))
if whichOne in myAs:
    changer( myAs[whichOne],"YeHaa")
    print(a1.text, a2.text)

Output:

whateverchanged never
Which element to change? ['A1', 'A2'] A2
whateverchanged neverYeHaa
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks your code helped me a lot, Im just learning so I really dont uderstand the whole picture. These user inputs i want it to be deliver to the program later, like from an API, Im unsure on how that works.
Here is the code I wanted it, as you said is some kind of dictionary , so i dont know the object to change, My final code is at the end
2

In Python, objects are passed by reference, so if you change any attribute of that object inside a function/method, it will be changed no matter if you use global or not.

The problem I am seeing in your logic is that you are never changing the value of the attribute, you should do something as:

object1.number = 123 # this is going to change that attribute no matter if you use the global keyword

Comments

0

In your function, by using this line:

real_obj_list[count]  = new_number  

you are not changing the actual object's value, you are just changing the value in the real_obj_list array.

I don't see what's wrong with using a simple assignment:

object1.number = 1

(which is nowhere to be seen in your function, hence the value is not updating).

But if you want a function for it, @PatrickArtner's answer pretty much sums it up.

Comments

0

If I change the value of current_object it will change the attribute as desired, want I wanted was to be able to choose in which object I will apply the attribute changer, that was why I could not use the direct way, thanks a lot.

current_object = "a"    
def matcher(object):    
    ref_list = ["a","b","c"]    
    real_list = [a,b,c]    
   count = -1    
    for item in ref_list:    
        count += 1    
        if item == object:    
            d = real_list[count]    
            return d    


class A():    
    pass    

a = A()    
b = A()    
c = A()    

var = matcher(current_object)    

def changer(o,newtext):    
    o.text =  newtext    

a.text = "bye"    
b.text = "hello"    
c.text = "Dunno"    

print(a.text)    
print(b.text)    
print(c.text)    

changer(var,"works")    

print(a.text)    
print(b.text)    
print(c.text)    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.