Python Wrap Class Method

前端 未结 4 1661
逝去的感伤
逝去的感伤 2021-02-07 18:05

I\'m trying to create an object with a run method that will be wrapped by a _wrap_run method. I\'d like to be able to call the method and it\'s wrapper by simply ty

相关标签:
4条回答
  • 2021-02-07 18:39

    Use a Metaclass.

    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()
    

    Now if other people subclass MyClass, they will still get their run() methods wrapped.

    0 讨论(0)
  • 2021-02-07 18:45

    Easiest way: make run the wrapper, and a private method be the overrideable one.

    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
    
    0 讨论(0)
  • 2021-02-07 18:46

    What you have there is basically a decorator, so why not go ahead and implement _wrap_run as a decorator and apply it when subclassing the function?

    0 讨论(0)
  • 2021-02-07 18:54

    What other folks do

    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
    

    That's usually sufficient.

    If you want to worry about someone "breaking" this, stop now. Don't waste time worrying.

    It's Python. We're all adults here. All the malicious sociopaths will break all you code by copying it, changing it, and then breaking it. No matter what you do, they'll just copy your code and modify it to break the clever bits.

    Everyone else will read your comment and stick by your rules. If they want to use your module/package/framework, they will cooperate.

    0 讨论(0)
提交回复
热议问题