2015-09-28 51 views
6

我想在返回代理对象的类上创建某种类型的描述符。代理对象在索引时检索对象的成员并将索引应用于它们。然后它返回总和。Python中的自适应描述符

例如,

class NDArrayProxy: 

    def __array__(self, dtype=None): 
     retval = self[:] 
     if dtype is not None: 
      return retval.astype(dtype, copy=False) 
     return retval 


class ArraySumProxy(NDArrayProxy): 

    def __init__(self, arrays): 
     self.arrays = arrays 

    @property 
    def shape(self): 
     return self.arrays[0].shape 

    def __getitem__(self, indices): 
     return np.sum([a[indices] 
         for a in self.arrays], 
         axis=0) 

这个解决方案工作得很好,而我实际的数组作为成员变量:

class CompartmentCluster(Cluster): 

    """ 
    Base class for cluster that manages evidence. 
    """ 

    def __init__(self, **kwargs): 
     super().__init__(**kwargs) 

     self.variable_evidence = ArraySumProxy([]) 

class BasicEvidenceTargetCluster(CompartmentCluster): 

    # This class variable creates a Python object named basic_in on the 
    # class, which implements the descriptor protocol. 

    def __init__(self, 
       *, 
       **kwargs): 
     super().__init__(**kwargs) 

     self.basic_in = np.zeros(self.size) 
     self.variable_evidence.arrays.append(self.basic_in) 

class ExplanationTargetCluster(CompartmentCluster): 

    """ 
    These clusters accept explanation evidence. 
    """ 

    def __init__(self, **kwargs): 
     super().__init__(**kwargs) 

     self.explanation_in = np.zeros(self.size) 
     self.variable_evidence.arrays.append(self.explanation_in) 

class X(BasicEvidenceTargetCluster, ExplanationTargetCluster): 
    pass 

现在我改变了我的阵列成Python描述符(cluster_signal实现了描述符协议返回一个numpy数组):

class CompartmentCluster(Cluster): 

    """ 
    Base class for cluster that manages evidence. 
    """ 

    def __init__(self, **kwargs): 
     super().__init__(**kwargs) 

     self.variable_evidence = ArraySumProxy([]) 

class BasicEvidenceTargetCluster(CompartmentCluster): 

    # This class variable creates a Python object named basic_in on the 
    # class, which implements the descriptor protocol. 

    basic_in = cluster_signal(text="Basic (in)", 
           color='bright orange') 

    def __init__(self, 
       *, 
       **kwargs): 
     super().__init__(**kwargs) 

     self.variable_evidence.arrays.append(self.basic_in) 

class ExplanationTargetCluster(CompartmentCluster): 

    """ 
    These clusters accept explanation evidence. 
    """ 

    explanation_in = cluster_signal(text="Explanation (in)", 
            color='bright yellow') 

    def __init__(self, **kwargs): 
     super().__init__(**kwargs) 

     self.variable_evidence.arrays.append(self.explanation_in) 

class X(BasicEvidenceTargetCluster, ExplanationTargetCluster): 
    pass 

这不起作用因为append语句会附加描述符调用的结果。我需要的是附加绑定方法或类似的代理。什么是修改我的解决方案最好的方法?简而言之:变量basic_inexplanation_innumpy阵列。他们现在是描述符。我想开发一些ArraySumProxy版本的描述符,而不需要实际的数组。

+0

我不完全理解你的问题。你能否展示你以前如何使用这些类,以及发生了什么变化,以及你希望在变化之后如何使用它们? – BrenBarn

+0

@brenbarn:总结。 –

+1

我无法从你的问题中知道哪些代码总是在使用中,哪些代码是新的。 –

回答

1

当你访问一个描述符时,它被评估,你只能得到这个值。由于你的描述符并不总是返回相同的对象(我猜你不能使用它),你不想在初始化代理时访问描述符。

最简单的方式,以避免访问它,就是只记得它的名字,所以不是:

self.variable_evidence.arrays.append(self.basic_in) 

你这样做:

self.variable_evidence.arrays.append((self, 'basic_in')) 

然后,当然,variable_evidence必须知道的,并做getattr(obj, name)来访问它。

另一种选择是使描述符返回稍后评估的代理对象。我不知道你在做什么,但是这可能是口感好太多代理...

编辑

或者......你可以存储,吸气:

self.variable_evidence.arrays.append(lambda: self.basic_in) 
+2

或者只是'lambda:self.basic_in'。 – user2357112

+0

但是再一次,一个代理有一个获取描述符的getter ...你需要所有这些吗? – zvone

+0

@ user2357112是的,这是更好的:) – zvone