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!

+3


source to share


5 answers


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

      

+5


source


use get :



self.files = self.options.get('--files', None)
if self.files:
    self.files.split(',')

      

+3


source


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.

+3


source


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.

+2


source


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.

+2


source







All Articles