2013-06-14 1 views
0

У меня есть класс, который вычисляет компоненты зарплаты, как показано ниже.Как установить переменную экземпляра в декораторе?

def normalize(func): 
    from functools import wraps 

    @wraps(func) 
    def wrapper(instance, *args, **kwargs): 
     allowanceToCheck = func(instance) 
     if instance.remainingAmount <= 0: 
      allowanceToCheck = 0.0 
     elif allowanceToCheck > instance.remainingAmount: 
      allowanceToCheck = instance.remainingAmount 
     instance.remainingAmount = instance.remainingAmount - allowanceToCheck 
     return allowanceToCheck 
    return wrapper 

class SalaryBreakUpRule(object): 
    grossPay = 0.0 
    remainingAmount = 0.0 

    @property 
    def basic(self): 
    # calculates the basic pay according to predefined salary slabs. 
    basic = 6600 # Defaulting to 6600 for now. 
    self.remainingAmount = self.grossPay - basic 
    return basic 

    @property 
    @normalize 
    def dearnessAllowance(self): 
     return self.basic * 0.2 

    @property 
    @normalize 
    def houseRentAllowance(self): 
     return self.basic * 0.4 

    def calculateBreakUps(self, value = 0.0): 
    self.grossPay = value 
    return { 
     'basic' : self.basic, 
     'da' : self.dearnessAllowance, 
     'hra' : self.houseRentAllowance 
    } 

Перед вычислением каждого пособия, мне нужно проверить, если сумма всех пособий не превышает grossPay т.е. моей общей зарплаты. Я написал декоратор, который обертывает каждый метод расчета надбавок и выполняет вышеупомянутое требование. Например,

* an employee having a salary of Rs.6700 
* basic = 6,600 (according to slab) 
* dearnessAllowance = 100 (cos 20% of basic is more than remaining amount) 
* houseRentAllowance = 0.0 (cos 40% of basic is more than remaining amount) 

Но, к сожалению, это не сработало. Первое пособие рассчитывается правильно, но всем остальным пособиям присваивается то же значение, что и первое пособие. i.e houseRentAllowance будет иметь 100 вместо 0.0, как указано выше.

Проблема, которую я нашел это, строка кода

instance.remainingAmount = instance.remainingAmount - allowanceToCheck 

в декоратор, где я пытаюсь установить переменную класса не работает.

Есть ли способ исправить эту проблему?

+0

Очень странно, это работает для меня. Действительно ли вы пытаетесь установить переменную класса или переменной экземпляра? – oleg

+0

Hi @oleg. Я считаю его переменной экземпляра. –

+3

Это не ваш фактический код. ('Класс' для' класса'). Пожалуйста, отправьте примерный пример, который иллюстрирует проблему. –

ответ

4

Вы сделали Salary.basic в собственность, а у Salary.basic() - побочные эффекты! Поэтому каждый раз, когда ваши другие функции ссылаются на self.basic, он пересчитывает и сбрасывает self.RemainingAmount в свое первоначальное значение, self.grossPay - basic.

Свойства с таким видом побочных эффектов: Плохой дизайн. Надеюсь, теперь вы видите, почему. Даже после того, как вы это исправите, доступ к вашим другим свойствам в другом порядке даст вам разные результаты. У владельцев объектов не должно быть долговременных побочных эффектов. В более общем плане: Сетчаты должны установить, геттеры должны получить. Свойства выглядят как простые переменные, поэтому они должны вести себя соответственно, иначе вы никогда не сможете понять или отладить свой код еще раз.

+0

Да, это была проблема, я думаю. Позвольте мне взглянуть и держать вас в курсе. Спасибо за ваше время и помощь. –

+0

Создание 'basic' в регулярной переменной должно исправить эту ошибку, но вы также должны отказаться от остальных своих свойств. Измените их на действия ('deductHouseRentAllowance()' и т. Д.) – alexis