Skip Huffman
Skip Huffman

Reputation: 5449

Handling names and values of attributes

I am probably approaching this wrong, but would appreciate being straightened out.

I would like to be able to use both the values and the names of some attributes of a class

Sample:

class DoStuff(object):
    def __init__(self):
        self.a="Alpha"
        self.b="Beta"
        self.c="Gamma"
    def printStuff(self):
        for thing in [self.a, self.b, self.c]:
            print NAMEOFTHING, thing

What I want is:

a Alpha
b Beta
c Gamma

How can I get that?

Edit: Some confusion because my example showed me printing ALL the values. Instead I want this:

a Alpha
c Gamma

with the list for my print method just having 'a' and 'c' in it.

Upvotes: 3

Views: 104

Answers (4)

Andrew Clark
Andrew Clark

Reputation: 208465

The way your class and for loop are set up, there is nothing you can put in place of NAMEOFTHING to get to the names of those variables. Here are a few alternatives on how you can modify your approach:

  • Use a dictionary instead of individual attributes, and then provide a list of keys in your for loop:

    class DoStuff(object):
        def __init__(self):
            self.names = {"a": "Alpha",
                          "b": "Beta",
                          "c": "Gamma"}
        def printStuff(self):
            for name in ['a', 'b', 'c']:
                print name, self.names[name]
    
  • Use the attribute names in your list and then use getattr():

    class DoStuff(object):
        def __init__(self):
            self.a="Alpha"
            self.b="Beta"
            self.c="Gamma"
        def printStuff(self):
            for name in ['a', 'b', 'c']:
                print name, getattr(self, name)
    

Upvotes: 8

Matt Tenenbaum
Matt Tenenbaum

Reputation: 1321

Following on Jon's answer, you might also find it helpful to set the list of attributes you want to include in the output as an optional argument:

def printStuff(self, included=['a', 'c']):
    for thing in included:
        print thing, getattr(self, thing)

which makes it easy to generate both outputs, by saying DoStuff().printStuff() to get just the values of a and c, or DoStuff().printStuff(['a', 'b', 'c']) to get all three. Of course, this allows for varying output—if it's an explicit design-goal that the set of fields being printed is invariant, this would be counterproductive.

Upvotes: 1

Goranek
Goranek

Reputation: 896

# You can use __dict__
>>> class x:
>>>     def __init__(self):
>>>         self.a = 1
>>>         self.b = 2
>>>         self.c = 3
>>>         self.d = 4

>>>     def prnt(self):
>>>         limit = "b", "c"
>>>         return {k:v for (k, v) in self.__dict__.iteritems()if k in limit}

>>> r = x()
>>> print r.prnt()
    {'b': 2, 'c': 3}

# __dict__ can be also done outside the class

limit = "b", "c"
print {k:v for (k, v) in r.__dict__.iteritems()if k in limit}

Upvotes: 0

Jon Clements
Jon Clements

Reputation: 142136

The closest you could get is:

for thing in ['a', 'b', 'c']:
    print thing, getattr(self, thing)

Variables can have multiple names and aren't aware of their own name, so if you know it's 'a', then you can use getattr to resolve the lookup.

Another option (although not greatly different than above)

to_get = ['a', 'b', 'c']
from operator import attrgetter
blah = zip(to_get, attrgetter(*to_get)(self))

Upvotes: 5

Related Questions