Property setter triggers infinite recursion, why?

Question:

Using the @property + setter encapsulation, I need a class that raises an exception when someone tries to change the account_number. However, in the __init__ function, I need to set the value. This is the code, it generates recursion.

class SingleBankAccount:
    
    def __init__(self, account_number, account_balance):
        self.account_number = account_number
        self.account_balance = account_balance
        
    @property
    def account_number(self):
        return self.account_number
        
    @account_number.setter
    def account_number(self, number):
    # if there is a number already, raise exception, otherwise set it
        if self.account_number:
            raise AccountException("Someone tried to change the account number!")
        else:
            self.account_number = number

This is the error:

File "main.py", line 17, in account_number

    if self.account_number:

  File "main.py", line 13, in account_number

    return self.account_number

  File "main.py", line 13, in account_number

    return self.account_number

  File "main.py", line 13, in account_number

    return self.account_number

  [Previous line repeated 993 more times]

RecursionError: maximum recursion depth exceeded

Plz help me understand why.

Answers:

You are setting the self.account_number property within the setter. The proper pythonic way is to use a "private" property:

class SingleBankAccount:
    
    def __init__(self, account_number, account_balance):
        self.account_number = account_number
        self.account_balance = account_balance
        
    @property
    def account_number(self):
        return self._account_number
        
    @account_number.setter
    def account_number(self, number):
    # if there is a number already, raise exception, otherwise set it
        if hasattr(self, "_account_number"):
            raise AccountException("Someone tried to change the account number!")
        else:
            self._account_number = number

hasattr is to avoid issues with the property not being set.

Answered By: sturgemeister