循环前面的类实例结果

时间:2017-02-23 12:29:52

标签: python numpy

这是here的延续。

我有一个B级,它包含一些数据(a和b字段)。

我正在将这些数据加载到Criteria类,以便通过标准并相应地更改调用函数avgfunccalcs

然后,我调用函数P开始运行带有数据的程序。

代码:

import numpy as np

class B():
    def __init__(self, a,b):
        self.a = a
        self.b = b
    def __repr__(self):
        return 'B(%s, %s)'%(self.a, self.b)


class Criteria():
    def __init__(self, method, minimum, maximum, measures=None):
        self.method = method
        self.minimum = minimum
        self.maximum = maximum
        self.measures = measures  

    def __repr__(self):
        if self.measures is None:
            measures = 'measures: None'
        else:
            measures = [' measures:[']
            for m in self.measures:
                measures.append('   {}'.format(m))
            measures.append('    ]')
            measures = '\n'+ '\n'.join(measures)
        return 'C({0.method},{0.minimum},{0.maximum}, {1})'.format(self, measures)


    def calcs(self):
        """ Update the `a` attribute from B class object according to 
         conditions
        """
        if self.measures is not None:
            for x in self.measures:
                if (x.a > self.minimum and x.a < self.maximum):
                    x.a = 999
        return self.measures

    def avg(self, calcs=None):
        """Return the average of values"""
        if calcs is None:
            calcs = self.measures
        if calcs is None:
            return 'none'
        elif len(calcs)==0:
            return '[]'
        else:
            return np.average([x.a for x in calcs])

    def func(self,calcs=None):
        """Return the minimum is input is array or multiple by 1000
        if input is a number"""
        if calcs is None:
            calcs = self.measures
        if calcs is None:
            return 'none'
        #elif len(calcs) == 0:
        #    return '[]'
        else:

            if isinstance(calcs, np.ndarray):
                return np.amin([x.a for x in calcs])
            else:
                return calcs*1000                       

def P(alist):

    # use these variables to hold the result of the corresponding execution
    # use them in the list loop in order to be able to obtain a result from a `Criteria` evaluation
    # and use it as input to the next
    last_calcs_values = None
    last_calcs_avg = None
    last_calcs_m = None

    for c in  alist:

        if c.method=='V':
            last_calcs_values = c.calcs()
            #print('calcs', last_calcs_values)
            yield last_calcs_values
        if c.method=='AVG':
            if c.measures is None:
                last_calcs_avg = c.avg(last_calcs_values)
            else:
                last_calcs_avg = c.avg()
            #print('AVG', last_calcs_avg)
            yield last_calcs_avg
        if c.method == 'M':
            if c.measures is None:
                last_calcs_m = c.func(last_calcs_avg)
            else:
                last_calcs_m = c.func()
            #print('M',last_calcs_m)
            yield last_calcs_m

如果我使用数据:

 b1 = np.array([B(10, 0.1), B(200,.5)])

c1 = Criteria('V', 1, 100, b1)
c2 = Criteria('AVG', 22, 220, None)
c3 = Criteria('M', 22, 220, None)

alist = [c1,c2,c3]

for i in P(alist):
    print(i)

我收到:

[B(999, 0.1) B(200, 0.5)]
599.5
599500.0

这是正确的。但是它起作用是因为P函数中的代码是硬编码的。

所以,

1)我的数据c1,c2,c3按顺序使用方法V,AVG,M

所以,在P函数中,我使用了:

   yield last_calcs_values

   last_calcs_avg = c.avg(last_calcs_values)
   yield last_calcs_avg

   last_calcs_m = c.func(last_calcs_avg)
   yield last_calcs_m

相同的订单(硬编码)。

我的问题是如何将此代码用于任何订单。我必须以某种方式检查前一个方法值是什么并将其放入参数中(而不是放入c.func(last_calcs_avg)

2)在func里面,我已经注释掉了这些行:

    #elif len(calcs) == 0:
    #    return '[]'

因为如果我运行代码,它会给出:object of type 'numpy.float64' has no len()

我尝试检查类似于稍后在func中的检查: if isinstance(calcs, np.ndarray):

但没有成功。

3)有没有办法只获得最后的结果?

所以,而不是:

[B(999, 0.1) B(200, 0.5)]
599.5
599500.0

获得:

599500.0

1 个答案:

答案 0 :(得分:1)

如果我正确阅读P,则会保持3&#39;状态&#39;变量。 3个if子句可以按任何顺序调用(我认为可以使用if,ifthen,ifthen,else语法编写,因为c.method只匹配一个(c

但是列表中对象的顺序将决定值。 AVG对象将使用最后一个V对象设置的值。同样,M将使用最后一个AVG。如果首先传递AVG,它将使用其计算中的初始None值。

因此V1, AVG, M的序列将使用由B设置的V1值。

在此序列V1, AVG, V2, M中,M使用上一个AVG的值,该值取决于V1;

avg如果func正在使用其值,或者至少测试必须匹配,则不应返回字符串。 []是一个空列表,len()为零,但'[]'为2个字符的字符串,len为2。

同样,None是使用is None测试的唯一值,而'none'是4个字符的字符串。我在之前的问题中使用了类似的字符串,因为我们打印的是avg的结果。当时我们还没有将它们用于进一步的计算。

如果您想确保AVGM使用上一个V中的值,则需要添加一些逻辑:

 lastV, lastA, lastM = None,None,None
 if c.method=='V':
     lastV = <newV>
     lastA, lastM = None,None
 elif c.method=='A':
     if lastV is None:
        error
     else:
        lastA = <new A based on lastV>
 elif c.method=='M':
     if lastA is None:
        error
        <or update lastA>
     else:
        lastM = <new M based on lastA>
 else:
     error unknown c.method

所以我使用None表示值无效。在这种情况下,它应该引发错误,或者应该计算新值。如果做得好,则应确保AVGM都会根据最新的V生成值。

从你的pastebin:

def avg(self, calcs=None):
    """Return the average of values"""
    if calcs is None:          # fun called without argument
        calcs = self.measures  # get value stored in self
    if calcs is None:          # in case that too was None
        return '[]'            # I would return None or []
                               # '[]' is a useless string
    else:
        if hasattr(calcs,'__len__'):
            return np.average([x.a for x in calcs])
        else:
            return np.average(calcs)

np.average()中哪些内容没有lenlen(np.arange(10))运行,但没有a属性

In [603]: avg(None,calcs=np.arange(10))
....
<ipython-input-602-48c9f6b255e1> in <listcomp>(.0)
      8     else:
      9         if hasattr(calcs,'__len__'):
---> 10             return np.average([x.a for x in calcs])
     11         else:
     12             return np.average(calcs)

AttributeError: 'numpy.int32' object has no attribute 'a'

具有__len__个对象的数组或列表与其他列表或数组之间的B。也许改进这个来测试dtype?或尝试/除外?

def avg(self,calcs = None):     &#34;&#34;&#34;返回值的平均值&#34;&#34;&#34;     ....     其他:         尝试:             return np.average([x.a for x in calcs])         除了AttributeError:             return np.average(calcs)

In [606]: avg(None,calcs=np.arange(10))
Out[606]: 4.5

B个对象的列表或数组有效:

In [609]: alist = [B(1,2),B(2,4),B(3,3)]
In [610]: avg(None, alist)
Out[610]: 2.0
In [611]: avg(None, np.array(alist))
Out[611]: 2.0