sta*_*art 1 python class dynamic getattr
我试图在运行时向现有类添加一个新类(使用"type(...)").我也试图覆盖新的类'__getattr__,以便我可以对不在新类中的属性执行自己的行为.例如,我有类foo,我添加类"工具",我希望foo.tool.test做我自己的事情.下面的代码有效但只是部分代码.如果我显式调用__getattr__,它可以工作(参见第一次打印),但是当我引用foo.tool.test时,我的被覆盖的__getattr__没有被调用,并且引发了一个属性错误.
非常感谢您的帮助.
class Foo(object):
def __init__(self):
self.NameList=[]
# add new class to ourself
self.tool = type('tool', (object,), {} )
# override new class' __getattr__ with call to ourself
setattr(self.tool, "__getattr__", self.__getattr__ )
# add one well known test name for now
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" % attr )
if( attr in self.NameList ):
return( 99 )
raise AttributeError("--%r object has no attribute %r" % (type(self).__name__, attr))
foo = Foo()
# access tool class attribute "test" - it should be seen by the override __getattr__
# the following works...
print( "foo.tool.__getattr__=%d" % foo.tool.__getattr__("test") )
# but the following does not - why is this not the same as the line above???
print( "foo.tool.test=%d" % foo.tool.test )
Run Code Online (Sandbox Code Playgroud)
Python __getattr__
在实例的基础中
查找特殊方法__dict__
,而不是在实例中__dict__
.
self.tool
是一个班级.self.tool.test
因此,将调用 __getattr__
的self.tool
的类(这是object
) -这不是我们所希望发生的.
相反,创建self.tool
一个实例,其类具有__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 )
Run Code Online (Sandbox Code Playgroud)
产量
foo.tool.__getattr__=99
foo.tool.test=99
Run Code Online (Sandbox Code Playgroud)
此外,要注意的是,上述代码可以导致无限递归如果实例Foo
在没有作出self.NameList
限定.请参阅Ned Batchelder关于这个令人惊讶的陷阱的帖子.
为了防止无限递归的可能性,请使用
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))
Run Code Online (Sandbox Code Playgroud)