0

I have a piece of code where I have an object B that has another object A as a property, and I would like the user to be able to set the properties of either object by name. How can I let the user set attributes of either A or B?

The following code illustrates what I am trying to do:

>>> class A:
...     def __init__(self):
...             self.asd = 123
>>> class B:
...     def __init__(self, a):
...             self.a = a
>>> a=A()
>>> b=B(a)
>>> b.a.asd
123
>>> setattr(b, 'a.asd', 1000)
>>> b.a.asd
123         # I would like this to be 1000

I would like to only prompt the user for the property name and value.

I am prompting the user with this code:

prop = input("Property name to set: ")
try: 
    print(f"Current value of property {prop}: {getattr(B, prop)}")
    value = input("Property value to set: ")
    setattr(B, prop, value)
except AttributeError:
    print(f"Object {B} has no property named {prop}. See {dir(B)}")

Edit: question solved, but I cannot accept my own answer for 2 days

6
  • 1
    Maybe: setattr(b.a, 'asd', 1000) ? Commented Sep 14, 2020 at 2:36
  • I can't prompt the user for b.a though. I want the user to be able to set properties of both A and B. Updated the question for clarity. Commented Sep 14, 2020 at 3:05
  • 1
    'a.asd' is a string. setattr will not interpret the '.' as anything more than a period. In your example, b is an object. b.a is a different object. setattr needs the exact object as its first argument - see the previous comment from @Mark Meyer Commented Sep 14, 2020 at 3:11
  • Can you share the user prompting code? Commented Sep 14, 2020 at 3:15
  • Updated the question with the prompt code. Commented Sep 14, 2020 at 3:18

2 Answers 2

1
setattr(getattr(b, 'a'), 'asd', 1000)
Sign up to request clarification or add additional context in comments.

3 Comments

How would I prompt the user for this info? I want the user to be able to set properties of both A and B
You prompt the user for this, the same way you prompt the user for any input. Where are you stuck? You now seem to be asking us to do some of your design and coding for you; this is off-topic for Stack Overflow.
@TheBicPen generally, you should be abstracting away the programming details from user input.
0

There is no way to traverse objects using the property name in setattr(). So to simulate this behaviour, you can split the property name on . and use getattr() to select the object you want to set the property on. This way, you only need to prompt the user for the property name and value.

prop = input("Property name to set: ")
obj_to_set = B
try:
    for i in prop.split(".")[:-1]:
        obj_to_set = getattr(obj_to_set, i)
    prop_name = prop.split(".")[-1]
    print(f"Current value of property {prop_name}: {getattr(obj_to_set, prop_name)}")
    value = input("Property value to set: ")
    setattr(obj_to_set, prop_name, value)
except AttributeError:
    print(f"Object {obj_to_set} has no property named {prop}. See {dir(obj_to_set)}")

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.