如何在类之间共享公共上下文?

时间:2012-03-22 02:08:27

标签: python class overlapping-instances

目前的情景:

我有一组在构造函数中都采用公共参数context的类,并且所有类都从公共库继承。

class base:
    def common_method(self):
        pass

class a(base):
    def __init__(self,context, aa):
        pass

class b(base):
    def __init__(self, context, bb):
        pass

# ...

class z(base):
    def __init__(self, context, zz):
        pass

主要用法:

context = get_context_from_some_method()

A = a(context, 1)
B = b(context, 2)
C = c(context, 3)
D = d(context, 4)
.
.
.
Z = z(context, 26)

问题:

  • 是否有一种方法可以隐式地向所有类提供context
  • 我们有一个共同的基类,但我没有看到让它为所有类设置上下文的明显方法。
  • 可以假设我想保持所有类实例的上下文。
  • 只是一个随意的想法 - 元类可以以某种方式帮助吗?

我知道这看起来很愚蠢,但我只是想以某种方式摆脱冗余,这样我就能以某种方式设置全局上下文并专注于我的对象。

请提出一些解决方法?

**更新问题**

  

我无法在基类中设置上下文,因为这将在Web应用程序中使用。因此,许多具有不同上下文的页面将使用类结构。因此,如果我在base中设置了一个上下文,那么它将与将使用相同基础的另一个网页实例设置的上下文冲突。因为,在Web应用程序中,所有上述类都将在所有页面共有的内存中。

4 个答案:

答案 0 :(得分:2)

编辑:如果您不想/不能使用类变量,最好的办法是使用工厂函数。要么使它成为基类的静态方法,要么是模块级函数。

def make_instances(context, *instances):
    return [cls(context, *args) for cls, args in instances]

A, B, ..., Z = make_instances(get_context_from_some_method(), 
                 (a, (1,)), (b, (2,)), ..., (z, (26,)))

# or
instances = make_instances(get_context_from_some_method(), 
             zip(list_of_subclasses, ((x,) for x in range(1, 27))))

或者,我不知道这是否适用于您的情况,只需使用模块级全局变量:

class z(base):
    def __init__(self, zz):
        self.zz = zz
        self.context = context

context = 'abc'
Z = z(26)

除了从其他答案中使用类变量的建议之外,我建议您将上下文复制到实例,以便以后可以更改上下文而不影响已创建的实例。< / p>

class base:
    context = None # if you want to be able to create without context.
    # just omit the previous line if you want an error
    # when you haven't set a context and you try to instantiate a subclass

class a(base):
    def __init__(self, aa):
        self.aa = aa
        self.context = self.context # sets an instance variable
        # so the class variable can be changed

class b(base):
    def __init__(self, bb):
        self.bb = bb
        self.context = self.context

base.context = 'context'

A = a(1)
B = b(2)

base.context = 'newcontext'

print A.context # context

答案 1 :(得分:1)

您可以使用类变量:

base.context = 'context'
A = a(1)
B = b(2)
#...

答案 2 :(得分:-1)

消除冗余的方法是识别重复的模式,并将模式分解为一些单独的代码。

不确定它是否是您的真实代码,但从您的示例来看,模式是您以类似的方式实例化一大堆类。即使您从键入context,所需的每一行中删除了9个字符,您仍然会这样做:

A = a(1)
B = b(2)
C = c(3)
...

哪会让我疯狂。冗余的问题不在于输入,而是如果你想改变它(比如你想从0开始,或者你想为每个类添加一个额外的参数,或者其他什么),你必须改变每一行

所以我宁愿做这样的事情:

classes = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]
instances = [cls(context, i) for i, cls in enumerate(classes, 1)]

这里我有代码清楚地说我正在实例化一大堆类,并且我正在向每个类传递上下文,以及从1到我所拥有的类数的整数(每个类增加) )。并且很容易独立决定改变类的列表,或者我传给每个类的内容。

这确实意味着我的实例的名称类似于instances[0]instances[13],而不是AN。也有方法,但我发现很少实例化一组东西,然后将它们用作独立的个体而不是集合。

答案 3 :(得分:-2)

您应该将上下文定义为 base 的类属性。修改你的例子是:

class base:

    context = None

    def common_method(self):
        pass

class A(base):
    def __init__(self, aa):
        pass

class B(base):
    def __init__(self, bb):
       pass

.
.
.

class Z(base):
    def __init__(self, zz):
        pass

base.context = get_context_from_some_method()
A = a(1)
B = b(2)
Z = z(3)    

所有A,B和Z实例共享相同的上下文属性。