题
问题:我有一个类,其中包含一个模板的方法 execute
它呼吁另一种方法 _execute
.子类,都应该复盖 _execute
要实现一些特定的功能。这个功能应该被记录在文档字符串的 _execute
.先进的用户可以建立自己的子类延长的图书馆。然而,另一个用户处理这样一个子类,只应使用 execute
, 所以他不会看到正确文档字符串如果他使用 help(execute)
.
因此,它将是很好的修改基类在这样一种方式,在一个亚类的文档字符串的 execute
是自动更换的 _execute
.任何想法,这怎么可能做了什么?
我想元类要做到这一点,使这完全透明的用户。
解决方案
好吧,如果你不介意的复原方法在子类,可以使用以下技术。
import new
def copyfunc(func):
return new.function(func.func_code, func.func_globals, func.func_name,
func.func_defaults, func.func_closure)
class Metaclass(type):
def __new__(meta, name, bases, attrs):
for key in attrs.keys():
if key[0] == '_':
skey = key[1:]
for base in bases:
original = getattr(base, skey, None)
if original is not None:
copy = copyfunc(original)
copy.__doc__ = attrs[key].__doc__
attrs[skey] = copy
break
return type.__new__(meta, name, bases, attrs)
class Class(object):
__metaclass__ = Metaclass
def execute(self):
'''original doc-string'''
return self._execute()
class Subclass(Class):
def _execute(self):
'''sub-class doc-string'''
pass
其他提示
是有一个原因,你不能替代的基类的 execute
功能直接?
class Base(object):
def execute(self):
...
class Derived(Base):
def execute(self):
"""Docstring for derived class"""
Base.execute(self)
...stuff specific to Derived...
如果你不想做的上述:
方法的对象不支持写入 __doc__
属性,所以你必须要改变 __doc__
在实际功能物体。因为你不想要复盖的一个基类中,你就必须得到每个子类自身的副本 execute
:
class Derived(Base):
def execute(self):
return Base.execute(self)
class _execute(self):
"""Docstring for subclass"""
...
execute.__doc__= _execute.__doc__
但是,这是类似于一种迂回的方式重新定义 execute
...
看看functools.包裹()装饰;它做所有这一切,但我不知道随便如果你能让它运行在正确的上下文
好doc-串的存在 __doc__
所以这不会太难以重新分配的基础上doc-串 _execute
之后的事实。
基本上:
class MyClass(object):
def execute(self):
'''original doc-string'''
self._execute()
class SubClass(MyClass):
def _execute(self):
'''sub-class doc-string'''
pass
# re-assign doc-string of execute
def execute(self,*args,**kw):
return MyClass.execute(*args,**kw)
execute.__doc__=_execute.__doc__
执行已被重新宣布,医生串获取附版本的执行 SubClass
而不是为 MyClass
(否则就会妨碍其他分类)。
这不是一个非常整洁的方式这样做,但从POV用户的图书馆应该得到期望的结果。然后您可以把这个包装在一个元类以使它更易为人们分分级.
我同意,最简单、最Python方式的接近,这是简单地执行重新定义你的子类,并呼吁执行方法的基类:
class Sub(Base):
def execute(self):
"""New docstring goes here"""
return Base.execute(self)
这是非常小的代码完成什么你想;唯一的缺点是,必须重复这样的代码,在每一个亚类,延伸的基础。然而,这是一个很小的代价的行为你想要的。
如果你想一种草率和详细的方式确保文档字符串用于执行的动态产生,你可以使用的描述符协议,该协议将明显较少的代码比其他建议在这里。这是令人讨厌是因为你不能只是设定一个描述的现有职能,这意味着执行必须是书面作为一个单独的类 __call__
法。
这里的代码这样做,但是请记住,我的上面的例子是更简单和更Python:
class Executor(object):
__doc__ = property(lambda self: self.inst._execute.__doc__)
def __call__(self):
return self.inst._execute()
class Base(object):
execute = Executor()
class Sub(Base):
def __init__(self):
self.execute.inst = self
def _execute(self):
"""Actually does something!"""
return "Hello World!"
spam = Sub()
print spam.execute.__doc__ # prints "Actually does something!"
help(spam) # the execute method says "Actually does something!"