我正在尝试使用将由_wrap_run method
包装的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
"""
答案 0 :(得分:14)
使用元类。
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()
方法包裹起来。
答案 1 :(得分: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
答案 2 :(得分:1)
你所拥有的基本上是decorator,那么为什么不继续将_wrap_run
作为装饰器来实现并在子类化函数时应用它?
答案 3 :(得分:1)
其他人做什么
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。我们都是成年人。所有恶意的反社会人士都会通过复制,更改它,然后打破它来破坏你所有的代码。无论你做什么,他们只需复制你的代码并修改它以打破聪明的位。
其他人都会阅读您的评论并遵守您的规则。如果他们想要使用你的模块/包/框架,他们会合作。