基本上,我有一个具有许多方法的泛型类。在访问这些方法之前,我必须检查它的'type'字段,例如:
注意:generic_class_t
来自第三方库,我无法控制或重新设计。我只能换行,但我想表现得更有表现力。
问题来了:
class generic_class_t:
def __init__(self):
self.type = ...
def method1(self):
pass
def method2(self):
pass
attr1 = property(lambda self: ...)
attr1 = property(lambda self: ...)
使用泛型类的用户代码,总是必须使用像这样的东西:
if cls.type == 1:
cls.method1()
cls.attr1
elif cls.type == 2:
cls.method2()
cls.attr2
...
我想做的是,把这个类包装成专门的类:
class cls1:
"""Wrapper for type=1"""
def __init__(self, cls):
self.obj = cls
def method1():
self.obj.method1()
attr = property(lambda self: cls.attr1)
# There are no method2, etc.
class cls2:
"""Wrapper for type=1"""
def __init__(self, cls):
self.obj = cls
def method2():
self.obj.method2()
attr = property(lambda self: cls.attr2)
# There are no method2, etc.
当然,现在我必须有一个工厂方法:
>或者:
def wrap(cls):
if cls.type == 1:
return cls1(cls)
elif cls.type == 2:
return cls2(cls)
问题在于内存和工厂的性能。
对于每个泛型类实例,必须构造另一个专门化对象。
我的问题是:是否有一种方法可以直接/快速地修补现有的泛型类实例并叠加专门化的cls1和cls2等?
我宁愿不创建一个新的对象。
我知道代理对象方法可以派上用场,但是,再一次,我们有代理对象本身。
我可以修补__dict__
/交换__dict__
等,并做一些快速反泛型类和专门化类劫持它的方法?
我希望这是清楚的。
谢谢你的建议。
谢谢!
我认为你低估了字典的力量。例如,假设您的通用接口有一个方法do
和一个属性attr
。你的工厂不需要一个巨大的if
语句来选择它需要的实现:
class Wrapper:
def __init__(self, obj):
self.obj = obj
class Type1(Wrapper):
def do(self):
return self.obj.method1()
@property
def attr(self):
return self.obj.attr1
class Type2(Wrapper):
def do(self):
return self.obj.method2()
@property
def attr(self):
return self.obj.attr2
type_map = {
1: Type1,
2: Type2
}
def type_factory(obj):
return type_map(obj.type)(obj)
这种方式允许您对底层对象执行任意操作。例如,通过一些调整,你可以得到这样一个版本:
class TypeCombined(Wrapper):
def do(self):
return self.obj.method1() + self.obj.method2()
@property
def attr(self):
return self.obj.attr1 + self.obj.attr2
def type_factory(obj, type=None):
return type_map[obj.type if type is None else type](obj)
如果您需要一些更简单的东西,因为每个类型都简单地对应于一组方法和属性,您可以使用类似元类的东西生成类,或者更简单地使用可配置的基类:
type_map = {
1: ('method1', 'attr1'),
2: ('method2', 'attr2')
}
class Wrapper:
def __init__(self, obj):
self.obj = obj
self.method_name, self.attr_name = type_map[obj.type]
def do(self):
return getattr(self.obj, self.method_name)()
@property
def attr(self):
return getattr(self.obj, self.attr_name)