Python looks for special methods like __getattr__
in an instance's bases
__dict__
s, not in the instance's __dict__
.
self.tool
is a class. self.tool.test
, therefore, will call the __getattr__
of self.tool
's class (which is object
) -- this is not what we want to happen.
Instead, make self.tool
an instance, whose class has a __getattr__
:
class Foo(object):
def __init__(self):
self.NameList=[]
# add new class to ourself
toolcls = type('tool', (object,), { '__getattr__' : self.__getattr__, } )
self.tool = toolcls()
self.NameList.append( "test" )
# should be called by our newly added "tool" object but is only called sometimes...
def __getattr__(self, attr):
# print("__getattr__: (%s, %s)" % (self.__class__.__name__, attr) )
if( attr in self.NameList ):
return( 99 )
raise AttributeError("--%r object has no attribute %r" % (
type(self).__name__, attr))
foo = Foo()
print( "foo.tool.__getattr__=%d" % foo.tool.__getattr__("test") )
print( "foo.tool.test=%d" % foo.tool.test )
yields
foo.tool.__getattr__=99
foo.tool.test=99
Also, beware that the above code can lead to infinite recursion if an instance of Foo
is made without self.NameList
being defined. See Ned Batchelder's post on this suprising pitfall.
To protect against the possibility of infinite recursion here, use
def __getattr__(self, attr):
# print("__getattr__: (%s, %s)" % (self.__class__.__name__, attr) )
if attr == 'NameList':
raise AttributeError()
if( attr in self.NameList ):
return( 99 )
raise AttributeError("--%r object has no attribute %r" % (
type(self).__name__, attr))