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