Метод класса Wrap Python

Я пытаюсь создать объект с помощью метода run, который будет обернут методом _wrap_run method. Я хотел бы иметь возможность вызывать метод и его обертку, просто набирая 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
"""

Ответ 1

Использование метакласса.

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

Ответ 2

Самый простой способ: сделать 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

Ответ 3

У вас есть в основном декоратор, так почему бы не пойти и реализовать _wrap_run в качестве декоратора и применить его при подклассификации функция?

Ответ 4

Что делают другие люди

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. Мы все взрослые здесь. Все злобные социопаты сломают все, что вы закодируете, скопировав их, изменив, а затем сломав. Независимо от того, что вы делаете, они просто копируют ваш код и изменяют его, чтобы разбить умные биты.

Все остальные будут читать ваши комментарии и придерживаться ваших правил. Если они хотят использовать ваш модуль/пакет/фреймворк, они будут сотрудничать.