2

Suppose I have a class like this:

class A:
    def __init__(self):
        self.a = "a"
        self.b = "b"

How would I get a dictionary like this ?

{"a": "a", "b": "b"}

I read this question and answers, but the dictionary in these answers always contains some "dunder" attributes as well, which I never defined in A.__init__. Will I have to use one of the solutions in the linked question and filter out the dunder attributes, or is there a smarter way ?

TheEagle
  • 5,808
  • 3
  • 11
  • 39
  • 3
    So, what do you get if you run for example `vars(A())`? I get what you want to have. – Klaus D. Jul 14 '21 at 20:42
  • 1
    @KlausD. OMG i'm dumb - I tried this instead `vars(A)` which gave the output in my question … – TheEagle Jul 14 '21 at 20:44
  • 1
    `vars` really just returns `A().__dict__`. – chepner Jul 14 '21 at 20:47
  • Hard to tell if this question is an _exact_ duplicate or not without specifying whether the attributes defined in `__init__` only should be returned, or any one set at any point after. The duplicate solves the question as answered, but the title remains open IMO. – TankorSmash Jul 14 '21 at 21:03
  • @TankorSmash `"whether the attributes defined in __init__ only should be returned"` - exactly, I want only these. – TheEagle Jul 14 '21 at 21:06
  • But there's nothing inherently special about the `__init__`-set attributes, compared to ones you add after. like `my_ad = A()`, then later you do `my_a.new_attr = 'some val'` outside of `__init__`, you still want to see `new_attr` in the dict, right? – TankorSmash Jul 14 '21 at 21:37
  • @TankorSmash no I don't want to see these, but I won't with the accepted solution, because I do `self.attrs = vars(A())` at the end of the `__init__` method ! – TheEagle Jul 15 '21 at 09:38

3 Answers3

8

You can do this by looking at the __dict__ attribute or using the vars function like so:

class A:
    def __init__(self):
        self.a = "a"
        self.b = "b"

print(A().__dict__)  # prints {'a': 'a', 'b': 'b'}
print(vars(A()))     # also prints {'a': 'a', 'b': 'b'}
chepner
  • 497,756
  • 71
  • 530
  • 681
PirateNinjas
  • 1,908
  • 1
  • 16
  • 21
1
class A:
    foo = 'bar'

    def __init__(self):
        self.a = "a"
        self.b = "b"

a = A()
print(vars(a)) # prints "{'a': 'a', 'b': 'b'}"
print({k: v for k, v in vars(A).items() if not k.startswith('__')}) # prints "{'foo': 'bar'}"
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
1

Perhaps I'm not understanding your question, but the easiest method for getting a dictionary of attributes like you described is as follows:

class A:
    def __init__(self):
        self.a = "A"
        self.b = "B"

x = A()

print(x.__dict__)

This should give you:

{a: "A", b: "B"}

The dict attribute is a dunder attribute, but it is the most elegant solution for this IMO. Is there a specific reason you'd like to avoid this method? If not, I recommend it for simplicity's sake.