python class 是否有将其实现委托给另一个 class 的模式?
Is there a pattern for a python class to delegate its implementation to another class?
对于这可能是一个基本问题,我深表歉意。我是一名 C++ 程序员,对 python 比较陌生。
我有一个 python class 其行为在很大程度上取决于其构造函数参数之一:
class MyClass():
def __init__(self, some_arg):
self.some_arg = some_arg
...
def abcd(self):
if self.some_arg == 1:
...
else:
...
def efgh(self):
if self.some_arg == 1:
...
else:
...
我想将其重构为两个具有不同 some_arg 值的 classes。当然,最直接的方法是拥有两个 classes(可能有一个共同的基础 class),然后让工厂函数选择要实例化的那个。大致如下:
def MyClassSomeArg1():
def __init__(self):
...
def abcd(self):
...
def efgh(self):
...
def MyClassSomeArgNot1():
def __init__(self):
...
def abcd(self):
...
def efgh(self):
...
def buildMyClass(some_arg):
if some_arg == 1:
return MyClassSomeArg1()
else:
return MyClassSomeArgNot1()
我相信那会很好。问题是我不想更改客户端代码。客户期望使用 some_arg 的构造函数参数实例化 class "MyClass" 的对象。有没有一种不错的方法可以在不更改客户端代码的情况下重构它?
我已经尝试使用一个实现层次结构:MyClassImpl 作为基础 class 与 subclasses MyClassImplSomeArg1 和 MyClassImplSomeArgNot1。然后 MyClass 本身大部分变成空的:
class MyClass():
def __init__(self, some_arg):
if some_arg == 1:
self._impl = MyClassImplSomeArg1()
else:
self._impl = MyClassImplSomeArgNone1()
def __getattr__(self, a):
# For performance, I could store this in self so it doesn't need to be looked up each time
return getattr(self._impl, a)
这基本上行得通,但似乎不是最直接的事情。一方面,像 __str__ 和 __eq__ 这样的魔术方法似乎没有通过 __getattr__ 机制进行委托,我不知道为什么。不过,自己编写委托方法并不困难。此外,这会使 pydoc 感到困惑(它无法查看委托属性),我不确定如何解决这个问题。
是否有一些糖分可以使这个授权计划很好地工作?还是授权甚至是处理此类问题的最佳方式?
谢谢,
您可以覆盖 __new__
函数和 return 基于 some_arg
的子类。这是实现 factory
的常见模式
class MyClassImplSomeArg1:
pass
class MyClassImplSomeArgNone1:
pass
class MyClass:
def __new__(cls, some_arg):
if some_arg:
return MyClassImplSomeArg1()
else:
return MyClassImplSomeArgNone1()
assert isinstance(MyClass(some_arg=True), (MyClassImplSomeArg1,))
assert isinstance(MyClass(some_arg=False), (MyClassImplSomeArgNone1,))
对于这可能是一个基本问题,我深表歉意。我是一名 C++ 程序员,对 python 比较陌生。
我有一个 python class 其行为在很大程度上取决于其构造函数参数之一:
class MyClass():
def __init__(self, some_arg):
self.some_arg = some_arg
...
def abcd(self):
if self.some_arg == 1:
...
else:
...
def efgh(self):
if self.some_arg == 1:
...
else:
...
我想将其重构为两个具有不同 some_arg 值的 classes。当然,最直接的方法是拥有两个 classes(可能有一个共同的基础 class),然后让工厂函数选择要实例化的那个。大致如下:
def MyClassSomeArg1():
def __init__(self):
...
def abcd(self):
...
def efgh(self):
...
def MyClassSomeArgNot1():
def __init__(self):
...
def abcd(self):
...
def efgh(self):
...
def buildMyClass(some_arg):
if some_arg == 1:
return MyClassSomeArg1()
else:
return MyClassSomeArgNot1()
我相信那会很好。问题是我不想更改客户端代码。客户期望使用 some_arg 的构造函数参数实例化 class "MyClass" 的对象。有没有一种不错的方法可以在不更改客户端代码的情况下重构它?
我已经尝试使用一个实现层次结构:MyClassImpl 作为基础 class 与 subclasses MyClassImplSomeArg1 和 MyClassImplSomeArgNot1。然后 MyClass 本身大部分变成空的:
class MyClass():
def __init__(self, some_arg):
if some_arg == 1:
self._impl = MyClassImplSomeArg1()
else:
self._impl = MyClassImplSomeArgNone1()
def __getattr__(self, a):
# For performance, I could store this in self so it doesn't need to be looked up each time
return getattr(self._impl, a)
这基本上行得通,但似乎不是最直接的事情。一方面,像 __str__ 和 __eq__ 这样的魔术方法似乎没有通过 __getattr__ 机制进行委托,我不知道为什么。不过,自己编写委托方法并不困难。此外,这会使 pydoc 感到困惑(它无法查看委托属性),我不确定如何解决这个问题。
是否有一些糖分可以使这个授权计划很好地工作?还是授权甚至是处理此类问题的最佳方式?
谢谢,
您可以覆盖 __new__
函数和 return 基于 some_arg
的子类。这是实现 factory
class MyClassImplSomeArg1:
pass
class MyClassImplSomeArgNone1:
pass
class MyClass:
def __new__(cls, some_arg):
if some_arg:
return MyClassImplSomeArg1()
else:
return MyClassImplSomeArgNone1()
assert isinstance(MyClass(some_arg=True), (MyClassImplSomeArg1,))
assert isinstance(MyClass(some_arg=False), (MyClassImplSomeArgNone1,))