猴子打补丁?代理对象?摆脱工厂方法并回收泛型对象



基本上,我有一个具有许多方法的泛型类。在访问这些方法之前,我必须检查它的'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)

相关内容

  • 没有找到相关文章