Python class 覆盖内部方法的装饰器
Python class decorator that overrides internal method
我正在尝试编写一个装饰器,它可用于在继承过程中覆盖方法,但在外部。
类似于:
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'
如果有人能就此分享一些想法,那就太好了!
以下是我将如何根据用例解决问题;
用于测试 - 如果您尝试动态覆盖方法,我会查看模拟库。这是资源 - https://docs.python.org/3/library/unittest.mock.html
FOR SEPARATE CLASS - 如果它是 class-wide 变化,我会选择覆盖原始方法的子 class;这将使您的代码更加明确
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'
正如其他人在评论中提到的,我认为这里不需要装饰器。这只是 class 属性分配的问题。
定义 class 时不会发生继承;来自父项的方法不会“引入”到子项 class。相反,它发生在属性查找期间。如果未定义 B.some_method
,则使用 A.some_method
的值。因此,要覆盖 parent-class 方法,您只需提供所需 class 属性的定义即可。方法只是具有 function
.
类型值的 class 属性
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
我正在尝试编写一个装饰器,它可用于在继承过程中覆盖方法,但在外部。 类似于:
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'
如果有人能就此分享一些想法,那就太好了!
以下是我将如何根据用例解决问题;
用于测试 - 如果您尝试动态覆盖方法,我会查看模拟库。这是资源 - https://docs.python.org/3/library/unittest.mock.html
FOR SEPARATE CLASS - 如果它是 class-wide 变化,我会选择覆盖原始方法的子 class;这将使您的代码更加明确
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'
正如其他人在评论中提到的,我认为这里不需要装饰器。这只是 class 属性分配的问题。
定义 class 时不会发生继承;来自父项的方法不会“引入”到子项 class。相反,它发生在属性查找期间。如果未定义 B.some_method
,则使用 A.some_method
的值。因此,要覆盖 parent-class 方法,您只需提供所需 class 属性的定义即可。方法只是具有 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