2016-06-29 2 views
3

Я довольно новичок в python, и я решил создать модуль для управления моим ежемесячным бюджетом в качестве учебного случая. Основной объект в модуле будет дебет, определяется какмаксимальная рекурсия превышена при вызове атрибута объекта

class Debit(object): 

    currency = "SEK" 

    def __init__(self,date,tag,ammount): 
     self.date = date 
     self.tag = tag 
     self.ammount = ammount  

Я хотел, чтобы иметь возможность контролировать, что атрибут этого объекта введены правильно, и сделать так что я пытался играть со свойствами, как это

@property 
def date(self): 
    return self.date 
@date.setter 
def date(self, d): 
    if len(d) == 0: 
     raise Exception("Date cannot be empty") 
     self.date = d 

NB: состояние и исключение в date.setter будет изменено в нечто более актуальным, я просто хотел попробовать исключение Это работает только наполовину: в самом деле, если я пытаюсь ввести пустой строка для даты, я получил исключение. Тем не менее, когда я вхожу в правильную дату, а затем я попытался получить с помощью .date я получил следующее сообщение об ошибке

RuntimeError: maximum recursion depth exceeded 

Я полагаю, что я делаю что-то плохое, называя «дата» в свойствах и сеттер, заставляя python в бесконечный цикл, но я не могу его обвести.

Любая помощь?

+1

дата называет себя рекурсивным. введите данные даты еще что-то вроде '_date' – syntonym

+0

Вы имеете в виду при инициализации объекта или внутри свойства и сеттера? –

+2

Всякий раз, когда вы обращаетесь к объекту object.date, вызывается функция 'def date (self)'. Поэтому, когда вы получаете доступ к self.date внутри этого ... вызывается 'date (self)'. Вы должны каким-то образом различать получателя и данные, которые он получает. Это часто делается путем наименования фактических данных '_data', так что, когда вы возвращаете' self._data', он не * вызывает 'date (self)'. – syntonym

ответ

3

Каждый объект имеет пространство имен (фактически dict), которое хранит его элементы - независимо от того, являются ли они атрибутами, функциями/методами или прочими вещами.

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

Теперь, если Debit.date были обычным методом, установка self.date = date в __init__ просто заменит метод на значение. Поскольку Debit.date является свойством, он использует настраиваемое поведение для установки значения - self.date = date не заменит свойство, но вызовет его сеттер Debit.date.setter.

Рекурсия возникает из-за того, что сеттер пытается записать в self.date, что также является свойством и, таким образом, пытается использовать Debit.date.setter.

@date.setter # makes the method available as `Debit.date` 
def date(self, d): 
    if len(d) == 0: 
    raise Exception("Date cannot be empty") 
    self.date = d # sets `Debit.date`, i.e. calls `Debit.date.setter(self, d)` 

Как было отмечено в комментариях к вашему вопросу, общий подход к вашему делу это назвать свойстваdate и атрибута_date. Это позволяет избежать столкновения имен, но дает понять, что они принадлежат друг другу.

class Debit(object): 
    currency = "SEK" 

    def __init__(self,date,tag,ammount): 
    self.date = date # use of self.date calls the setter to set self._date with input checking 
    self.tag = tag 
    self.ammount = ammount 

    @property 
    def date(self): # property getter 
    return self._date # provide attribute 

    @date.setter 
    def date(self, d): # property setter 
    if len(d) == 0: 
     raise Exception("Date cannot be empty") 
    self._date = d # set attribute 
Смежные вопросы