8

In Python when writing file management scripts I will often have a base path that is a constant,

BASE = "C:/"

Of course I'll be using that base path to create other paths later on, including other paths that will change in no other place. So I define constants like this:

SUB_FOLDER = os.path.join(PROJECT_BASE, "folder")

However it feels like it may be contrary to define what is a constant based on the result of a function call, even if that call will return a fixed result and never be modified.

Is this considered poor style that would confuse people?

3
  • 1
    I get your question, but I would not follow this specific example: hard coded disk letters/folders are always a bad idea.
    – Jan Doggen
    Nov 13, 2015 at 14:42
  • 1
    @JanDoggen In my case it's based specifically on inhouse server paths, not for public distribution. If the file path ever changes/doesn't exist then someone's made a massive mistake and it's not me (or at least... it's not the script I made a mistake in) Nov 13, 2015 at 14:44
  • 1
    I don't know what reason you have not to expect the file path to ever change. Perhaps it's a good reason, but when it stops being true, eventually your hard coded disk letters may end up being that reason. That's a scenario generally worth avoiding. Nov 13, 2015 at 16:28

2 Answers 2

13

This would be considered a run-time constant: the value cannot be known before the program starts, but it is unchanging throughout the entire application once set.

The major advantage to a run-time constant is that it makes it obvious to a developer that the value is unchanging and that it enforces this in some way (to prevent erroneous assignments when the value has already been set), but you acknowledge that it cannot be known until run-time. Compare the value of Pi (which can be known and set before runtime) to the installation path of an application (which can only be figured out once the application starts, but not change when the application is running).

Your example perfectly fits the bill for this: it is a value that is set once and will never change throughout your application and therefore can look like a constant. Just note that this is not a true constant as Python does not have them and you will therefore need some kind of workaround to actually enforce their constant-ness.

5
  • Thank you for the answer! I'm aware that Python enforces no constants, I'm just going to use the names this way so it's clear what type of value it is. Nov 13, 2015 at 14:33
  • Interestingly, Java only supports such run-time constants. final indicates that a variable can only be initialized and not reassigned (but does not restrict modification of non-final member variables). I don't know if the static compiler detects cases where finals are initialized in their declaration and optimizes those out into compile-time constants (though that would only work for primitive values or trivial objects where every recursive member is final and initialized in its declaration) or if it just leaves that up to the JIT compiler, though.
    – JAB
    Nov 13, 2015 at 15:36
  • (Java also has enumerated types, but those are essentially run-time constants as well as they are classes and thus loaded lazily, only when actually needed, meaning you could inject alternate types via a custom class loader.)
    – JAB
    Nov 13, 2015 at 15:37
  • @JAB the JLS has a definition which says which expressions are compile-time constant. When there is a method call in there, it is not one. Nov 13, 2015 at 18:08
  • @PaŭloEbermann Which, by extension, means object creation (other than for Strings) would not be compile-time constant. So just primitives (and Strings) then. (Which I just found is explicitly stated in the section on final: docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4)
    – JAB
    Nov 13, 2015 at 18:38
3

Setting BASE and using its value this way is what you want to do.

Now if you need to tweak a few months from now it is only defined in one place in the code. Imagine if your boss told you to new store those files on the X drive; You would need to find all places where you mention "c:/" and change them to "x:/". Don't make a mistake or files will be written to the wrong place, and ones you need to read won't be found.

SUB_FOLDER isn't a constant. Its value is determined a split second after program execution starts. Again defining it this way helps in program maintenance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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