Python Wrap类方法

时间:2011-07-21 18:31:59

标签: python class methods wrapper

我正在尝试使用将由_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
"""

4 个答案:

答案 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。我们都是成年人。所有恶意的反社会人士都会通过复制,更改它,然后打破它来破坏你所有的代码。无论你做什么,他们只需复制你的代码并修改它以打破聪明的位。

其他人都会阅读您的评论并遵守您的规则。如果他们想要使用你的模块/包/框架,他们会合作。