-1

My question regards to constants in Python. Which is more "convenient" or "acceptable" among software engineers in general:

  1. Putting classes of constants in another file called "consts.py" as such:

consts.py

class Messages:
    GREETING = "You are greeted by {greeted_person}"

or in a class of classes of constants as such:

consts.py

class Constants:
   class Messages:
      GREETING = "You are greeted by {greeted_person}"

Also, when I have only one single "topic" to cover with only one constant, is it necessary to make a whole class just for it? or let it stand alone in the consts.py file?

Thank you!

1
  • 1
    Since you are working in Python you could leverage the module / package structure to namespace your messages. So you would import messages and would refer to the string with messages.GREETING. No class was warmed for this. Jun 5 at 8:18

1 Answer 1

3

Do the simplest thing that works, given your requirements.

Quite often, this is going to mean to not name constants at all. In a lot of software, this is perfectly fine:

print(f"You are greeted by {person}")

If you want to reuse the same message in multiple places then it can make sense to extract it:

print(greeting(person))

...

def greeting(person):
  return f"You are greeted by {person}"

If those multiple users are in different modules, then extracting messages into a module of their own can make sense.

# file /foo.py
from .messages import greeting

print(greeting(person))

# file /messages.py
def greeting(person):
  return f"You are greeted by {person}"

If you want to be able to override messages e.g. for localization purposes then it can make sense to introduce a class so that you can pass a messages object around:

# file /foo.py
def do_stuff(messages):
  print(messages.greeting(person))

# file /messages.py
class Messages:
  def greeting(self, person):
    return f"You are greeted by {person}"

class MessagesDe(Messages):
  def greeting(self, person):
    return f"Sie werden von {person} gegrüßt"

# file /__main__.py
from .foo import do_stuff
from .messages import Messages, MessagesDe

def main(language):
  if language == "de":
    messages = MessagesDe()
  else:
    messages = Messages()

  do_stuff(messages)

if __name__ == "__main__":
  main(*sys.argv[1:])

Though in reality, you'd use a localization framework that is likely going to handle the selected language more implicitly (without having to pass around a messages object), and will keep translations in data files rather than in code.

So what does this mean for your proposed solutions?

  • having a consts.py file? Probably OK and definitely common, but I'm not a fan because the concept of “constants” isn't a domain concept of your application. Note that my examples use messages.py as a name to better express the meaning/purpose of that module. However, putting constants into a shared module is of course great if multiple other modules need to access that data.

  • having a Messages class? Absolutely fantastic if you want to pass around instances of that class. Probably superfluous if you're using a class just as a namespace. This isn't Java, you can just use a module.

  • having a nested Constants.Messages class? Probably less of a good idea. As with the previous bullet point, you shouldn't use classes just as namespaces in Python. Use classes if you want to create instances. The way how nested classes behave in Python can be unintuitive so that it's usually best to avoid defining classes anywhere else but the top-level of a module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.