What is the right way to treat Python argparse.Namespace() as a dictionary?

PythonDictionaryDuck Typing

Python Problem Overview


If I want to use the results of argparse.ArgumentParser(), which is a Namespace object, with a method that expects a dictionary or mapping-like object (see collections.Mapping), what is the right way to do it?

C:\>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import argparse
>>> args = argparse.Namespace()
>>> args.foo = 1
>>> args.bar = [1,2,3]
>>> args.baz = 'yippee'
>>> args['baz']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Namespace' object has no attribute '__getitem__'
>>> dir(args)
['__class__', '__contains__', '__delattr__', '__dict__', '__doc__', '__eq__', '_
_format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__
', '__str__', '__subclasshook__', '__weakref__', '_get_args', '_get_kwargs', 'ba
r', 'baz', 'foo']

Is it proper to "reach into" an object and use its __dict__ property?

I would think the answer is no: __dict__ smells like a convention for implementation, but not for an interface, the way __getattribute__ or __setattr__ or __contains__ seem to be.

Python Solutions


Solution 1 - Python

You can access the namespace's dictionary with vars():

>>> import argparse
>>> args = argparse.Namespace()
>>> args.foo = 1
>>> args.bar = [1,2,3]
>>> d = vars(args)
>>> d
{'foo': 1, 'bar': [1, 2, 3]}

You can modify the dictionary directly if you wish:

>>> d['baz'] = 'store me'
>>> args.baz
'store me'

Yes, it is okay to access the __dict__ attribute. It is a well-defined, tested, and guaranteed behavior.

Solution 2 - Python

Straight from the horse's mouth:

> If you prefer to have dict-like view of the attributes, you can use the standard Python idiom, vars(): > > >>> parser = argparse.ArgumentParser() > >>> parser.add_argument('--foo') > >>> args = parser.parse_args(['--foo', 'BAR']) > >>> vars(args) > {'foo': 'BAR'} > > — The Python Standard Library, 16.4.4.6. The Namespace object

Solution 3 - Python

Note that if you're trying to treat args as a dict to find out if it has an attribute, you can just do the following instead:

if hasattr(args, 'someProperty'):
    a.someProperty

more info on hasattr and similar answer to another question

Also, you can get the value if you prefer using the similar getattr method:

value = getattr(args, 'someProperty')

Solution 4 - Python

> Is it proper to "reach into" an object and use its dict property?

In general, I would say "no". However Namespace has struck me as over-engineered, possibly from when classes couldn't inherit from built-in types.

On the other hand, Namespace does present a task-oriented approach to argparse, and I can't think of a situation that would call for grabbing the __dict__, but the limits of my imagination are not the same as yours.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJason SView Question on Stackoverflow
Solution 1 - PythonRaymond HettingerView Answer on Stackoverflow
Solution 2 - PythonEugene YarmashView Answer on Stackoverflow
Solution 3 - PythonBrad ParksView Answer on Stackoverflow
Solution 4 - PythonmswView Answer on Stackoverflow