Skip to content

8 min read

American Corners

Attributes and methods

The two halves of an object

Every object is made of two kinds of thing. Attributes are the data it carries, the nouns: a balance, a name, a page count. Methods are the actions it can take, the verbs: deposit, describe, add interest. A class is really just a place to keep a set of attributes and the methods that work on them together, so they never drift apart.

We will build up a simple savings account to see both, and to meet one more distinction that trips people up: data that belongs to a single object versus data shared by every object of the class.

Instance attributes: one object's own data

An instance attribute belongs to one object and one object only. You set it up in __init__, using self, and each object gets its own copy.

class SavingsAccount:
    def __init__(self, owner, balance):
        self.owner = owner        # this account's owner
        self.balance = balance    # this account's balance

If you make two accounts, each has its own owner and balance. Changing one leaves the other alone, because self.balance always means "the balance of this account", not some global number.

Class attributes: data shared by all

A class attribute is different: it belongs to the class itself, so every object sees the same value. It is written straight inside the class body, not inside __init__. A good use is something that is genuinely the same for all objects, such as an interest rate the bank sets for every account.

class SavingsAccount:
    interest_rate = 0.03          # class attribute: shared by all accounts

    def __init__(self, owner, balance):
        self.owner = owner        # instance attribute: unique to each account
        self.balance = balance

Here owner and balance differ from account to account, but interest_rate is one value shared by all of them. If the bank raises the rate on the class, every account reflects the new rate at once. That is the signal for using a class attribute: when the value is a property of the whole kind, not of any single object.

Methods, getters and setters

Methods are functions defined inside the class; their first parameter is always self, so they can read and change that object's attributes. Some methods just report a value, and some change it in a controlled way. The convention of a method that reads an attribute is a getter, and a method that updates one is a setter.

class SavingsAccount:
    interest_rate = 0.03

    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

    def get_balance(self):                  # getter: just reports
        return self.balance

    def deposit(self, amount):              # setter-style: changes, with a check
        if amount > 0:
            self.balance = self.balance + amount

    def add_interest(self):                 # uses the shared class attribute
        self.balance = self.balance + self.balance * SavingsAccount.interest_rate

Now the account can be used through its methods rather than by poking at its data directly.

account = SavingsAccount("Household fund", 1000)
account.deposit(500)
print(account.get_balance())    # 1500
account.deposit(-40)            # rejected by the check, balance unchanged
print(account.get_balance())    # 1500

Tip

The point of going through deposit instead of writing account.balance = account.balance + 500 by hand is the guard inside it. A setter can refuse bad input, such as a negative deposit, so the object protects its own data. That habit is what makes objects trustworthy as a program grows.

Attributes hold the state, methods control how that state is read and changed, and keeping instance data separate from shared class data lets one blueprint serve many objects cleanly. The next step is letting one class build on another.

Prefer to see it explained? Here is the recorded Code for Albania lecture on this topic.

Try this now

Write a class Student with a class attribute school shared by all students, instance attributes name and points set in __init__, and a method add_points(amount) that adds only when amount > 0. Make two students, add points to one, try adding a negative amount, and print both point totals to see the guard work.

Check yourself

  1. Explain the difference between an instance attribute and a class attribute, and give one example of each from the savings account where the choice clearly makes sense.
  2. Why is calling account.deposit(500) safer than writing account.balance = account.balance + 500 directly? What can the method do that the plain assignment cannot?
  3. If the bank changes interest_rate on the class after several accounts already exist, which of those accounts are affected, and why?

Where this lesson comes from

Built from

  • Data Structures and Algorithms

alphaPlan courses are built from taught programmes rather than invented for the web. Where a claim rests on an outside standard or a reported case, it is named above so you can check it rather than take our word for it.

This course was developed by alphaPlan Center from programs delivered in partnership with the American Corners network.

Found something unclear, outdated or improvable? Suggest an improvement