我想创建一个包装另一个类的类,这样当一个函数在包装类中运行时,也会运行pre和post函数。我希望包装器类可以在不修改的情况下使用任何类。
例如,如果我有这门课程。
class Simple(object):
def one(self):
print "one"
def two(self,two):
print "two" + two
def three(self):
print "three"
我可以像这样使用它......
number = Simple()
number.one()
number.two("2")
到目前为止,我已经编写了这个包装类......
class Wrapper(object):
def __init__(self,wrapped_class):
self.wrapped_class = wrapped_class()
def __getattr__(self,attr):
return self.wrapped_class.__getattribute__(attr)
def pre():
print "pre"
def post():
print "post"
我可以这样打电话......
number = Wrapper(Simple)
number.one()
number.two("2")
除了更改第一行之外,可以使用与上面相同的内容。
我想要发生的是当通过包装类调用一个函数时,包装类中的pre函数被调用,然后是包装类中的所需函数,然后是post函数。我希望能够在不更改包装类的情况下执行此操作,也无需更改函数的调用方式,只需更改创建类实例的语法。例如number = Simple()vs number = Wrapper(Simple)
答案 0 :(得分:26)
你几乎就在那里,你只需要在__getattr__
内进行一些内省,当原始属性可以调用时返回一个新的包装函数:
class Wrapper(object):
def __init__(self,wrapped_class):
self.wrapped_class = wrapped_class()
def __getattr__(self,attr):
orig_attr = self.wrapped_class.__getattribute__(attr)
if callable(orig_attr):
def hooked(*args, **kwargs):
self.pre()
result = orig_attr(*args, **kwargs)
# prevent wrapped_class from becoming unwrapped
if result == self.wrapped_class:
return self
self.post()
return result
return hooked
else:
return orig_attr
def pre(self):
print ">> pre"
def post(self):
print "<< post"
现在使用此代码:
number = Wrapper(Simple)
print "\nCalling wrapped 'one':"
number.one()
print "\nCalling wrapped 'two':"
number.two("2")
结果是:
Calling wrapped 'one':
>> pre
one
<< post
Calling wrapped 'two':
>> pre
two2
<< post
答案 1 :(得分:2)
我刚才注意到在我的原始设计中没有办法将args和kwargs传递给包装类,这里是更新的答案,将输入传递给包装函数...
class Wrapper(object):
def __init__(self,wrapped_class,*args,**kargs):
self.wrapped_class = wrapped_class(*args,**kargs)
def __getattr__(self,attr):
orig_attr = self.wrapped_class.__getattribute__(attr)
if callable(orig_attr):
def hooked(*args, **kwargs):
self.pre()
result = orig_attr(*args, **kwargs)
self.post()
return result
return hooked
else:
return orig_attr
def pre(self):
print ">> pre"
def post(self):
print "<< post"