-2

This question has already been asked, but not exactly like this (I can't use any of the answers): I want to call a function that returns a dictionary, and if this dictionary is not None, loop on it and use its key + values on an object. NB: this object is from a class and its class can't be modified. Something like:

def check_ok(s):
  return {'prop_1': 'x',
          'prop_2': 'y'}


def check_and_update(obj, st):
    result = check_ok(st)
    if result is not None:
        for k, v in result.items():
            obj.k = v  # doesn't work, of course

What is the solution?

drekbour
  • 2,895
  • 18
  • 28
Olivier Pons
  • 15,363
  • 26
  • 117
  • 213
  • Technically you *should* be able to add new members to an existing object in python. What error do you get when you try to set the new attribute? – user32882 Aug 26 '20 at 14:52
  • Can you please provide a minimal implementation of the class? – jkr Aug 26 '20 at 14:53

2 Answers2

3

You can achieve that by:

  1. Creating your own class
  2. By using the set_attr method to add those values to the object's dictionary
def check_ok(s):
  return {'prop_1': 'x',
          'prop_2': 'y'}


class UpdateableObject(object):
    pass

def check_and_update(obj, st):
    result = check_ok(st)
    if result is not None:
        for k, v in result.items():
            setattr(obj, k, v)

uob = UpdateableObject()
# Passed None because the `check_ok` functions doesn't use the `st` parameter
check_and_update(uob, None)

# {'prop_1': 'x', 'prop_2': 'y'}
print(f'{uob.__dict__}')
Aviv Yaniv
  • 6,188
  • 3
  • 7
  • 22
1

Let me interprete the sentence "NB: this object is from a class and its class can't be modified." in the meaning of: You can't modify the code of the class, but modifying instance attributes will work.

Then you can use setattr to modify the object:

def check_and_update(obj, st):
    result = check_ok(st)
    if result is not None:
        for k, v in result.items():
            setattr(obj, k, v)

Furthermore, implementing early stopping/exiting may be a good idea, depending on how long your code is (and depending on what you want to do in this case). This removes one level of indentation of your code and makes it easier to read the code, since the "reader" is not waiting/looking for an elif or else clause:

def check_and_update(obj, st):
    result = check_ok(st)
    if result is not None:
        return  # or whatever you want to do here
    for k, v in result.items():
        setattr(obj, k, v)

And if for some reason the obj of the class is in fact not mutable, you can always try to inherit from that class and overwrite the critical parts:

class MyMutableClass(ImmutableClass):
    def __init__(self, arguments):
         pass  # do whatever is necessary to make changes...
JE_Muc
  • 5,403
  • 2
  • 26
  • 41