假设我有不同的类,提供对不同子系统的访问,但具有通用接口。它们都提供相同的方法集,但每个类以不同的方式实现它们(想想使用foo.write()写入文件或通过套接字发送数据等)
由于接口是相同的,我想创建一个能够选择正确类但只基于构造函数/初始化器参数的类。
在代码上,它看起来像
class Foo(object):
def who_am_i(self):
print "Foo"
class Bar(object):
def who_am_i(self):
print "Bar"
# Class that decides which one to use and adds some methods that are common to both
class SomeClass(Foo, Bar):
def __init__(self, use_foo):
# How inherit methods from Foo -OR- Bar?
SomeClass
如何从[{1}} 或 Foo
继承Bar
和/或__init__
参数?< / p>
目标应该是
__new__
是否有一些干净的&#34; pythonic&#34;实现这个的方法?我并不想使用函数动态定义>>> some_object = SomeClass(use_foo=True)
>>> some_object.who_am_i()
Foo
>>> another_object = SomeClass(use_foo=False)
>>> another_object.who_am_i()
Bar
,但我没有找到另一种方法来执行此操作。
谢谢!
答案 0 :(得分:3)
如评论中所述,这可以通过工厂函数(假装为类的函数)来完成:
def SomeClass(use_foo):
if use_foo:
return Foo()
else:
return Bar()
答案 1 :(得分:1)
这里可以使用班级工厂。请注意使用字典来确保相同的子类实例用于每个基类。
def makeclass(baseclass, classes={}):
if baseclass not in classes:
class Class(baseclass):
pass # define your methods here
classes[baseclass] = Class
return classes[baseclass]
obj1 = makeclass(Foo)(...)
obj2 = makeclass(Bar)(...)
isinstance(obj1, makeclass(Foo)) # True
isinstance(obj1, Foo) # True
issubclass(makeclass(Foo), Foo) # True
issubclass(type(obj1), Foo) # True
您还可以使用dict
方法创建__missing__
子类,以完成相同的操作;它让你更明确地知道你有一个存储类的容器,但是按需创建它们:
class ClassDict(dict):
def __missing__(self, baseclass):
class Class(baseclass):
pass # define your methods here
self[baseclass] = Class
return Class
subclasses = ClassDict()
obj1 = subclasses[Foo]
obj2 = subclasses[Bar]
答案 2 :(得分:1)
据我所知,你的继承完全倒退;而不是你提出的多重继承:
Foo Bar
- foo code - bar code
\ /
SomeClass(Foo, Bar)
- common code
您可以使用更简单的单继承模型:
SomeClass
- common code
/ \
Foo(SomeClass) Bar(SomeClass)
- foo code - bar code
这使您的问题成为选择实例化哪个子类(只需要进行一次的决策)而不是调用哪个超类方法(可能需要在每个方法调用上进行)。这可以通过以下方式解决:
thing = Foo() if use_foo else Bar()
答案 3 :(得分:0)
由于对答案缺乏一致意见,可能问题就在于问题。 jonrsharpe's comment对此问题提供了一个有趣的见解:这应该通过继承来解决 。
考虑SomeClass
定义如下:
# Class that uses Foo or Bar depending on the environment
# Notice it doesn't subclasses either Foo or Bar
class SomeClass(object):
def __init__(self, use_foo):
if use_foo:
self.handler = Foo()
else:
self.handler = Bar()
# Makes more sense asking 'Who implements?' instead of 'Who am I?'
def who_implements(self):
return self.handler
# Explicitly expose methods from the handler
def some_handler_method(self, *args, **kwargs):
return self.handler.some_handler_method(*args, **kwargs)
def another_handler_method(self, *args, **kwargs):
return self.handler.another_handler_method(*args, **kwargs)
我们是否需要获取有关处理程序实现的详细信息,只需获取handler
属性即可。子类SomeClass
的其他类甚至不会直接看到处理程序,这实际上是有意义的。
答案 4 :(得分:-1)
可以使用__new__
方法实现此目的:
_foos = {}
_bars = {}
class SomeClass(object):
def __new__(cls,use_foo,*args,**kwargs):
if use_foo:
if cls not in _foos:
class specialized(cls,Foo):pass
_foos[cls] = specialized
else:
specialized = _foos[cls]
else:
if cls not in _bars:
class specialized(cls,Bar):pass
_bars[cls] = specialized
else:
specialized = _bars[cls]
specialized.__name__ = cls.__name__
return object.__new__(specialized,*args,**kwargs)
#common methods to both go here
pass
这比工厂函数的优点是isinstance(SomeClass(True),SomeClass)
有效,SomeClass
可以被子类化。