我正在尝试编写一个装饰器,该装饰器可用于在继承期间但在外部覆盖方法。 类似的东西:
class A:
def some_method(self):
print('does stuff')
def override(method):
# override decorator
....
def some_method_override():
print('does other stuff')
@override(method, some_method_override)
class B:
#overridden
a = A()
b = B()
a.some_method() # prints 'does stuff'
b.some_method() # prints 'does other stuff'
如果有人能就此分享一些想法,那就太好了!
答案 0 :(得分:0)
以下是我将如何根据用例解决问题;
用于测试 - 如果您尝试动态覆盖方法,我会查看模拟库。这是一个资源 - https://docs.python.org/3/library/unittest.mock.html
对于单独的类 - 如果是类范围的更改,我会使用覆盖原始方法的子类;这将使您的代码更加明确
class A:
def some_method(self):
print('do_stuff_a')
class B(A):
def some_method(self):
print('do_stuff_b')
a = A()
a.some_method() # print 'do_stuff_a'
b = B()
a.some_method() # prints 'do_stuff_b'
对于特定情况 - 如果您只希望有时发生这种行为,我会使用状态观察者代码模式 - 这是一个示例
class A:
def __init__(self)
self._use_method_a = True
def use_method_a(self, use_method_a):
self._use_method_a = use_method_a
def some_method(self):
if self._use_method_a:
return self._method_a()
else:
return self._method_b()
def _method_a(self):
print('do_stuff_a')
def _method_b(self):
print('do_other_stuff_b')
a = A()
a.some_method() # print 'do_stuff_a'
a.use_method_a(False)
a.some_method() # prints 'do_other_stuff_b'
答案 1 :(得分:0)
正如其他人在评论中提到的,我认为这里不需要装饰器。这只是类属性分配的问题。
定义类时不会发生继承;来自父类的方法不会“拉入”到子类。相反,它发生在属性查找期间。如果未定义 B.some_method
,则使用 A.some_method
的值。因此,要覆盖父类方法,您只需提供所需类属性的定义。方法只是具有 function
类型值的类属性。
class A:
def some_method(self):
print('does stuff')
def some_method_override(self):
print('does other stuff')
class B(A):
some_method = some_method_override
a = A()
b = B()
a.some_method() # prints 'does stuff'
b.some_method() # prints 'does other stuff'
如果你确实想要一个装饰器,它就是这样的
def override(old: str, new: Callable):
def _(cls):
setattr(cls, old, new)
return cls
return _
def some_method_override(self):
print('does other stuff')
class A:
def some_method(self):
print('does stuff')
@override('some_method', some_method_override)
class B(A):
pass