IntEnum возвращает ошибку атрибута: не удается установить атрибут

#python #python-3.x #unit-testing #class #enums

#python #python-3.x #модульное тестирование #класс #перечисления

Вопрос:

Это тревожная проблема. Для функции:

 def influencePositive(q1, q2):
    if(q1.magnitude.greaterZero()):
        q2.derivative.value = DValue.add(q2.derivative.value, 1)
  

Следующий модульный тест выполняется без проблем:

 def test_i_plus_active(self):
        q1 = Quantity(Magnitude(MValue.PLUS), None)
        q2 = Quantity(None, Derivative(DValue.ZERO))

        r.influencePositive(q1, q2)
        self.assertEqual(q2.derivative.value, DValue.PLUS)
  

Но для этой другой функции:

 def exogenous(q1, q2, value):
    if type(value) == int:
        q2.derivative.value = DValue.add(q1.derivative.value, value)
  

Следующий unittest прерывается:

 def test_ex_increase_minus(self):
        q1 = Quantity(None, DValue.MINUS)
        q2 = Quantity(None, DValue.MINUS)

        r.exogenous(q1, q2, 1)
        self.assertEqual(q2.derivative.value, DValue.ZERO)
  

Возникает ошибка атрибута: ошибка атрибута: не удается установить атрибут. Это весь обратный путь:

 Traceback (most recent call last):
  File "C:/Users/Victor Zuanazzi/Documents/Artificial Intelligence/Knowledge Representation/Practicals/Qualitative_Reaoning/relationFunction_test.py", line 121, in test_ex_increase_minus
    r.exogenous(q1, q2, 1)
  File "C:UsersVictor ZuanazziDocumentsArtificial IntelligenceKnowledge RepresentationPracticalsQualitative_ReaoningrelationFunctions.py", line 31, in exogenous
    q2.derivative.value = DValue.add(q1.derivative.value, value)
  File "C:ProgramDataAnaconda3libtypes.py", line 146, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute
  

Вот некоторые базовые знания для понимания приведенного выше кода.

dValue — это IntEnum:

 from enum import IntEnum

class DValue(IntEnum):
    MINUS = -1
    ZERO = 0
    PLUS = 1

    @staticmethod
    def add(dvalue, delta):
        return max(min(dvalue   delta, DValue.PLUS), DValue.MINUS)
  

Мы используем это для установки производной класса:

 class Derivative:
    def __init__(self, value):

        #if value is type int, it is converted to Enum.
        if value is int:
            value = DValue(value)

        self.value = value
  

Количество — это класс, для экземпляров которого установлены величины и производные значения:

 from magnitude import Magnitude, MValue
from derivative import Derivative, DValue

class Quantity:
    def __init__(self, magnitude, derivative):
        self.magnitude = magnitude
        self.derivative = derivative
  

Я не понимаю, почему influencePositive() работает просто отлично и exogenous() ломается. Они оба вызывают DValue.add() одинаково.

Ответ №1:

Вот ваша проблема:

В случае вашего первого теста производным является Derivative объект, чей .value атрибут может быть переназначен. В вашем втором тесте производным является DValue ( IntEnum ) объект, .value атрибут которого не может быть переназначен.

 In [4]: d = Derivative(DValue.ZERO)

In [5]: d.value
Out[5]: <DValue.ZERO: 0>

In [6]: d.value = 1

In [7]: d.value
Out[7]: 1

In [8]: d = DValue.MINUS

In [9]: d.value
Out[9]: -1

In [10]: d.value = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-3c0164b4d46d> in <module>()
----> 1 d.value = 1

/home/ethan/.local/lib/python2.7/site-packages/enum/__init__.pyc in __set__(self, instance, value)
     54 
     55     def __set__(self, instance, value):
---> 56         raise AttributeError("can't set attribute")
     57 
     58     def __delete__(self, instance):

AttributeError: can't set attribute
  

Итак, я думаю, что ваш второй тест должен быть настроен q2 так, может быть:

 q2 = Quantity(None, Derivative(DValue.MINUS))
  

Комментарии:

1. Это сработало! Это стало очевидным после того, как вы указали, я был просто полностью слеп к этому.

2. да, это было довольно сложно, поскольку оба класса имеют .value !