In Python, what is the minimum way to assign a value to a variable depending on whether the dictionary contains a key?
I want to access multiple values in a dictionary, like this:
self.userName = self.options["--username"]
self.files = self.options["--files"].split(",")
self.configurationFileName = self.options["--configuration"]
However, it may be that some of these keys may not exist in the dictionary - say, "files" may not exist in it. If the key doesn't exist in the dictionary, I want the variable's value to be set to None
i.e. self.files = None
... I am currently doing something like the following:
if "--files" in self.options:
self.files = self.options["--files"].split(",")
else:
self.files = None
Will there be some way to do this that is a little more minimal, efficient, or Pythonic? I would prefer this to be done in a one-line space for clarity. Thank!
source to share
Use get
both the default empty string and replace with None
in case of empty string or empty list:
self.files = self.options.get('--files', "").split(",") or None
This way is split
always called on a valid object and you get None
if the object is empty.
EDIT
Actually, the tests I have used split()
which uses a different algorithm than split(",")
To work it must be
self.files = self.options.get('--files', "").replace(',', '\n').split() or None
Another way to do it with operations set
:
self.files = set(self.options.get('--files', "").split(",")) ^ set(['']) or None
but then it self.files
is a set, not a list.
secondary:
what i would do is define a small helper class
class NoneFound:
@classmethod
def split(self, _):
return None
and then just:
self.files = self.options.get('--files', NoneFound).split(',')
See the definition of this class:
>>> print {'--files': "a,b,c"}.get("--files", NoneFound).split(',')
['a', 'b', 'c']
>>> print {}.get("--files", NoneFound).split(',')
None
source to share
Pythonic way to get the key of a dictionary with a default value if the key is missing get
, like
self.user_name = self.options.get("--username", None)
self.configuration_file_name = self.options.get("--configuration", None)
As for the file option, you can use the same approach and split after that:
self.files = self.options.get("--files", None)
if self.files:
self.files = self.files.split(",")
or use a try / except block:
try:
self.files = self.options["--files"].split(",")
except KeyError:
self.files = None
or, if you really want it on one line, use a conditional:
self.files = self.options["--files"].split(",") if "--files" in self.options else None
I'm guessing at opinions on how to handle "files", most Pythonic will be different. I would go with the first case above (use get
and check split after that) because it is consistent with usage get
, which is definitely a Python way of handling the generic case of an unknown dictionary value, and I find this way of handling splitting logic the most obvious and straightforward.
Note that since you are asking how to be Pythonic, I used underscore_case instead of camelCase. This is the Python way of naming variables.
source to share
In general, the Pythonic technique is to use a try-except block, especially if you expect the operation to be successful in most cases. See EAFP .
try:
self.files = self.options["--files"].split(",")
except KeyError:
self.files = None
If you expect this to be successful in most cases, you can first check how you did it (see LBYL ). In general, this is not very important, use whatever method makes the most sense in your application.
source to share
I would take a step back and ask, "Why am I storing a comma delimited string in self.options['--files']
instead of a list in the first place?" If you did, then your code will simply
self.files = self.options.get("--files")
Anything that fills self.options
in has to split the list first.
source to share