mixin helper class for unknown attribute access?
Steven D'Aprano
steve at REMOVETHIScyber.com.au
Mon Oct 31 08:44:36 EST 2005
On Mon, 31 Oct 2005 12:47:16 +0000, Alex Hunsley wrote:
> Sorry, as I noted in another reply not long ago, I was having a 'braino'
> and not saying what I actually meant!
> What I was talking about was the accidental _setting_ of the wrong
> attribute.
> And the mixin class I'm looking for is one that could be told what were
> valid attributes for the class,
Who decides what are valid attributes for a class? The class writer, or
the class user who may want to use it in ways the writer never imagined?
> and would then catch the situation where
> you mis-spelt an attribute name when setting an attrib.
If all you care about is preventing developers from adding any new
attributes at run time, you can do something like this:
# warning: untested
class Example:
def __init__(self, data):
self.__dict__['data'] = data
def __setattr__(self, name, value):
if self.__dict__.has_key(name):
self.__dict__[name] = value
else:
raise AttributeError
except that the developers will then simply bypass your code:
p = Example(None)
p.__dict__['surprise'] = 1
p.surprise
Trying to prevent setting new attributes is a pretty heavy-handed act just
to prevent a tiny subset of errors. Many people argue strongly that even
if you could do it, it would be pointless -- or at least, the cost is far
greater than whatever small benefit there is.
But, if you insist, something like this:
# Warning: untested.
class Declare:
def __init__(self, names):
"""names is a list of attribute names which are allowed.
Attributes are NOT initialised.
"""
self.__dict__['__ALLOWED'] = names
def __setattr__(self, name, value):
if name in self.__ALLOWED:
self.__dict__[name] = value
else:
raise AttributeError("No such attribute.")
If you want to initialise your attributes at the same time you declare
them, use:
# Warning: untested.
class DeclareInit:
def __init__(self, names):
"""names is a dictionary of attribute names/values which are
allowed.
"""
self.__dict__ = names
def __setattr__(self, name, value):
if self.__dict__.has_key(name):
self.__dict__[name] = value
else:
raise AttributeError("No such attribute.")
Of the two approaches, I would say the second is marginally less of a bad
idea.
--
Steven.
More information about the Python-list
mailing list