Python encapsulation and properties

Keep validation next to the state it protects.

Python
class Account:
    def __init__(self):
        self._balance = 0
    @property
    def balance(self):
        return self._balance
    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("deposit must be positive")
        self._balance += amount

account = Account()
account.deposit(25)
print(account.balance)
try:
    account.deposit(0)
except ValueError:
    print("Rejected")
assert account.balance == 25
Output
25
Rejected

Explanation

Encapsulation groups state with operations that maintain its rules. This account stores nonnegative integer units and rejects nonpositive deposits.

A read-only property exposes the balance through the public interface. A leading underscore is a convention for internal use, not enforced private access or a security boundary.

Explore the dry run
Guided walkthroughReady
1class Account:
2 def __init__(self):
3 self._balance = 0
4 @property
5 def balance(self):
6 return self._balance
7 def deposit(self, amount):
8 if amount <= 0:
9 raise ValueError("deposit must be positive")
10 self._balance += amount
11
12account = Account()
13account.deposit(25)
14print(account.balance)
15try:
16 account.deposit(0)
17except ValueError:
18 print("Rejected")
19assert account.balance == 25

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Initialize the balance.balance = 0
—
Pass a positive amount.amount = 25
—
Add the deposit.balance = 25
—
Read through the property.balance = 25
25
Try a zero deposit.amount = 0
25
Reject it before changing state.balance = 25
25
The caller handles the expected error.balance = 25
25
Rejected

Cost and common mistakes

O(1) work and space per bounded deposit.

  • Do not bypass validation by assigning internal state directly.
  • This teaching account omits persistence, concurrency, and currency rounding.

Try it yourself

Try a deposit of -5 and then check the balance.

Reveal answer and reasoning

It raises ValueError and the balance remains 25.

Further reading