I have a situation in which I'm asked to read collections of database update instructions from a variety of sources. All sources will contain a primary key value so that the code that applies the updates to the database can find the correct record. The files will vary, however, in what additional columns are reported.
When I read and create my update instructions I must differentiate between an update in which a column (for instance, MiddleName) was provided but was empty (meaning no middle name and the field should be updated to NULL) and an update in which the MiddleName field was not included (meaning the update should not touch the middle name column at all).
The former situation (column provided but no value) seems appropriately represented by the None value. For the second situation, however, I'd like to have a NotInFile "value" that I can use similar to the way I use None.
Is the correct way to implement this as follows?
NotInFile = 1
class PersonUpdate(object):
def __init__(self):
self.PersonID = None
self.FirstName = NotInFile
self.MiddleName = NotInFile
and then in another module
import othermod
upd = othermod.PersonUpdate()
if upd.MiddleName is othermod.NotInFile:
print 'Hey, middle name was not supplied'
If you want type-checking, this idiom is now blessed by PEP 484 and supported by mypy:
If you are using mypy 0.740 or earlier, you need to workaround this bug in mypy by using typing.Final:
If you are using Python 3.7 or earlier, you can use
typing_extensions.Final
from pip packagetyping_extensions
instead oftyping.Final
No, using the integer one is a bad idea. It might work out in this case if
MiddleName
is always a string orNone
, but in general the implementation is free to intern integers, strings, tuples and other immutable values as it pleases. CPython does it for small integers and constants of the aforementioned types. PyPy definesis
by value for integers and a few other types. So ifMiddleName
is 1, you're bound to see your code consider it not supplied.Use an
object
instead, each new object has a distinct identity:Alternatively, for better debugging output, define your own class:
If you're paranoid, you could make it a proper singleton (ugly). If you need several such instances, you could rename the class into
Sentiel
or something, make the representation an instance variable and use multiple instances.I don't see anything particularly wrong with your implementation. however,
1
isn't necessarily the best sentinel value as it is a cached constant in Cpython. (e.g.-1+2 is 1
will returnTrue
). In these cases, I might consider using a sentinel object instance:python also provides a few other named constants which you could use if it seems appropriate:
NotImplemented
andEllipsis
come to mind immediately. (Note that I'm not recommending you use these constants ... I'm just providing more options).