CodingCat
CodingCat

Reputation: 5411

Python - Change attributes through dictionary

I'm writing a python script to collect data from various files into objects with a number of attributes. Each of these attribute can basically be "ok", "bad", or "N/A". Which of the attributes are "N/A" changes according to the parameters I call the script with.

What I want to do is initiate all objects with all these attributes set to "ok" by default, then set those that have not been measured to "N/A" (which is checked by a function returning a list of N/A-attributes). (Then later I collect the data from the files to set the attributes that are "bad" to "bad".)

I thought I could do that via a dictionary, but it doesn't seem to work/access the attributes?

class Myclass:
    def __init__(self, ID):
        self.ID = ID
        self.at1 = "ok"
        self.at2 = "ok"
        self.at3 = "ok"
        self.at4 = "ok"
        # there are a LOT more of these attributes

def foo(unused):
    for i in range(3):
        blurb = Myclass(i)
        unused_dic = {"at1":blurb.at1, "at2":blurb.at2,
                      "at3":blurb.at3, "at4":blurb.at4}
        for key in unused:
            unused_dic[key] = "N/A"
        print blurb.ID, blurb.at1, blurb.at2, blurb.at3, blurb.at4

unused = ["at1","at3"] # this is returned by another function
foo(unused)

The output of this is:

0 ok ok ok ok
1 ok ok ok ok
2 ok ok ok ok

But I would expect and want:

0 N/A ok N/A ok
1 N/A ok N/A ok
2 N/A ok N/A ok

What am I doing wrong, and how can I do it right?

Upvotes: 1

Views: 314

Answers (3)

Emmanuel
Emmanuel

Reputation: 14209

I tried to adopt a style more object-oriented; the setattr function is what you need:

>>> class Myclass:
    def __init__(self, ID):
        self.ID = ID
        self.at1 = "ok"
        self.at2 = "ok"
        self.at3 = "ok"
        self.at4 = "ok"

    def __str__(self):
    return str((self.at1, self.at2, self.at3, self.at4))

    def unused(self, unused):
    for attr in unused:
            setattr(self, attr, 'N/A')
    print self


>>> unused = ["at1","at3"]
>>> for i in range(3):
    m = Myclass(i)
    m.unused(unused)


('N/A', 'ok', 'N/A', 'ok')
('N/A', 'ok', 'N/A', 'ok')
('N/A', 'ok', 'N/A', 'ok')

Upvotes: 1

rxdazn
rxdazn

Reputation: 1390

You are not modifying your blurb object. You are modifying values from unused_dict.

You need to change your loop to this :

    for key in unused:
          if key in unused_dic:
              setattr(blurb, key, "N/A") # set attribute 'key' of object blurb to "N/A"

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121744

You are not changing the attributes on the instance, only in the dictionary itself. Variables in python are not pointers; changing a string in one place won't make the change visible elsewhere.

You can use setattr() to dynamically change attributes on an instance:

def foo(unused):
    for i in range(3):
        blurb = Myclass(i)
        for key in unused:
           setattr(blurb, key, "N/A")

But you'll have to store the blurb instance somewhere, the above code just 'drops the ball' so to speak.

Upvotes: 4

Related Questions