Python 包装类方法
我想创建一个对象,这个对象里面有一个叫做 run
的方法,并且这个方法会被一个 _wrap_run
方法包裹起来。我希望能够通过简单地输入 instance.run()
来调用这个方法和它的包装器。同时,我还想能够对这个对象进行子类化,这样我就可以重写 run()
方法,但仍然能让它执行包装器的内容。
简单来说,我希望大家可以对 A 这个类进行子类化,并重写 run()
方法,但调用 run()
方法时仍然能执行包装器函数。
我在实现这个功能时遇到了一些困难。有没有人对此有建议?
class A:
def run(self):
print "Run A"
return True
def _wrap_run(self):
print "PRE"
return_value = self.run()
print "POST"
return return_value
run = property(_wrap_run)
a = A()
a.run()
"""
Should Print:
PRE
Run A
POST
"""
class B(A):
def run(self):
print "Run B"
return True
b = B()
b.run()
"""
Should Print:
PRE
Run B
POST
"""
5 个回答
2
其他人是怎么做的
class A:
def do_run( self ):
"""Must be overridden."""
raise NotImplementedError
def run( self, *args, **kw ):
"""Must not be overridden.
You were warned.
"""
print "PRE"
return_value = self.do_run(*args, **kw)
print "POST"
return return_value
class B(A):
def do_run(self):
print "Run B"
return True
这通常就足够了。
如果你担心有人会“破坏”这个,赶紧停下。别浪费时间去担心。
这是Python。我们都是成年人。那些恶意的人会通过复制你的代码、修改它,然后把它搞坏。无论你做什么,他们都会复制你的代码,改动它来破坏那些聪明的部分。
其他人会看你的评论,并遵守你的规则。如果他们想使用你的模块、包或框架,他们会配合的。
5
最简单的方法是:让 run
成为一个包装函数,然后把一个私有方法作为可以被重写的部分。
class A(object):
def run(self):
print "PRE"
return_value = self._inner_run()
print "POST"
return return_value
def _inner_run(self):
print "Run A"
return True
class B(A):
def _inner_run(self):
print "Run B"
return True
26
使用元类。
class MetaClass(type):
@staticmethod
def wrap(run):
"""Return a wrapped instance method"""
def outer(self):
print "PRE",
return_value = run(self)
print "POST"
return return_value
return outer
def __new__(cls, name, bases, attrs):
"""If the class has a 'run' method, wrap it"""
if 'run' in attrs:
attrs['run'] = cls.wrap(attrs['run'])
return super(MetaClass, cls).__new__(cls, name, bases, attrs)
class MyClass(object):
"""Use MetaClass to make this class"""
__metaclass__ = MetaClass
def run(self): print 'RUN',
myinstance = MyClass()
# Prints PRE RUN POST
myinstance.run()
现在,如果其他人继承了 MyClass
,他们的 run()
方法也会被自动处理。