Detecting whether a value was passed for a parameter (was: skipping __init__ and using exploiting a class member instead)
Ben Finney
ben+python at benfinney.id.au
Sun Oct 20 07:50:57 EDT 2013
Peter Cacioppi <peter.cacioppi at gmail.com> writes:
> I was laboring under some misconception that there was Python magic
> that allowed __init__ and only __init__ to add class attributes by
> setting their values. Good to know this piece of magic isn't part of
> Python, and thus lazy eval can be handled more cleanly than I
> originally thought.
Rather, the magic is that ‘__init__’ will be called automatically by the
class creation protocol, to initialise any new instance of that class.
So the method to write if you want instance-specific initialisation is
still ‘__init__’.
> Think about it this way. None here really means "not yet initialized".
> It is a value that cannot occur naturally and thus functions as a
> not-initialized flag.
As you point out, though, that's not a menaing of None agreed on
everywhere. You can't expect that the caller will not be passing a value
of None for that parameter.
> So this, somewhat arbitrary, context sensitive value should be isolated
> as much as possible. You don't want it popping up hither and yon, you
> want to type as infrequently as possible and localized it to as few
> methods as possible.
Right. The pattern you're looking for is called a “sentinel value”
<URL:https://en.wikipedia.org/wiki/Sentinel_value>.
Usually, the None singleton is good enough for a sentinel value, but
often it has a meaning already in your context, so is not available as a
sentinel value.
In cases where None is not available, make a specific value that has no
other meaning, and use that specifically for your parameter's sentinel
value::
class Foo(object):
_default_for_x = object()
def __init__(self, x=_default_for_object):
""" Initialise a new instance. """
if x is self._default_for_object:
# No value for ‘x’ was passed, because ‘_default_for_x’
# would not be passed by accident.
x = self._get_value_for_x()
self.x = x
def _get_default_value_for_x(self):
"""" Calculate the default ‘x’ value for this instance. """
return some_computation(self)
--
\ “When a well-packaged web of lies has been sold to the masses |
`\ over generations, the truth will seem utterly preposterous and |
_o__) its speaker a raving lunatic.” —Dresden James |
Ben Finney
More information about the Python-list
mailing list