python父类'包装'的孩子
我的python代码中有以下情况:
class Parent(object):
def run(self):
print "preparing for run"
self.runImpl()
print "run done"
class Child(Parent):
def runImpl(self):
print "child running"
然而,我有几个这样的“装饰器”,在'runImpl'之前和之后进行不同的设置/拆卸步骤,我不喜欢定义run()
, runImpl()
, runImplSingleProcess()
等。
我正在寻找以下形式的解决方案:
class Parent(object):
@wrapping_child_call
def run(self, func_impl, *args, **kwargs)
print "preparing for run"
func_impl(*args, **kwargs)
print "run done"
class Child(Parent):
def run(self):
print "child running"
通过这种方式,Child类几乎不需要意识到这一点。
多重继承也可能存在问题。 如果一个Child
继承Parent1
和Parent2
,我真的不知道应该是什么正确的行为。
有没有人知道一个很好的,自然的方式来完成这个? 还是我在这里强奸设计?
谢谢
Yonatan
不要在这里使用继承
颠倒你的设计。 为什么不只是有一个组合,所以你得到一个“有一个”的关系,而不是一个“是 - 一个”关系的亲子实现? 您可以定义实现您想要的方法的类,而您的上一个父类将使用那些实现特定的类来实例化。
class MyClass:
def __init__(self, impl)
self.impl = impl
def run(self,var):
print "prepare"
impl.runImpl(var)
print "I'm done"
class AnImplementation:
def runImpl(self,var):
Yonatan,你的问题不清楚! 根据情况,您可以使用许多不同的设计。
一种解决方案是在调用runImpl()之前有显式的setup()和teardown()方法,这些方法由run()方法调用。 这将允许子类根据需要来包装/覆盖这些。
class Runner(object):
def run(self):
self.setup()
self.runImpl()
self.teardown()
def setup(self):
pass
def teardown(self):
pass
class RunnerImplementation(Runner):
def runImpl(self):
pass # do some stuff
def setup(self):
print "doing setup"
super(RunnerImplementation, self).setup()
def teardown(self):
print "doing teardown"
super(RunnerImplementation, self).teardown()
但是,您提到了多重继承,这意味着这不是您应该采取的方向。
你提到的多重继承和包装(如“装饰器”)让我猜测你希望能够编写不同的“runner”实现,每个实现都有其自己的设置/拆卸过程,同时重新使用之间的setup / teardown部分不同的“跑步者”。
如果是这种情况,你可以定义知道如何设置和拆卸自己的资源,并让每个跑步者声明它需要的资源。 run()方法将运行每个资源的相关设置/拆卸代码,并使其可用于runImpl()方法。
class Resource(object):
name = None # must give a name!
def setup(self):
pass
def teardown(self):
pass
class DatabaseResource(Resource):
name = "DB"
def setup(self):
self.db = createDatabaseConnection()
def teardown(self):
self.db.close()
class TracingResource(Resource):
name = "tracing"
def setup(self):
print "doing setup"
def teardown(self):
print "doing teardown"
class Runner(object):
RESOURCES = []
def run(self):
resources = {}
for resource_class in self.RESOURCES:
resource = resource_class()
resource.setup()
resources[resource_class.name] = resource
self.runImpl(resources)
# teardown in opposite order of setup
for resource in reversed(resources):
resource.teardown()
class RunnerA(Runner):
RESOURCES = [TracingResource, DatabaseResource]
def runImpl(self, resources):
resources['DB'].execute(...)
你可以得到这个:
class Parent(object):
def run(self, func_impl, *args, **kwargs):
print "preparing for run"
func_impl(*args, **kwargs)
print "run done"
class Child(Parent):
@wrapped_in_parent_call
def run(self):
print "child running"
附:
import functools
class wrapped_in_parent_call(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
@functools.wraps(self.func)
def wrapped(*args, **kwargs):
owning_class = self.func.__get__(obj, type).im_class
parent_func = getattr(super(owning_class, obj), self.func.__name__)
return parent_func(
lambda *a, **kw: self.func(obj, *a, **kw),
*args,
**kwargs
)
return wrapped
(仅限Python 2)
链接地址: http://www.djcxy.com/p/44151.html