Table of Contents
Understanding Attributes and Methods in Classes
In object-oriented programming, attributes and methods are the two main things that make up a class. Attributes store data, and methods define behavior.
This chapter focuses on:
- What attributes are and how to define/use them
- What methods are and how to define/use them
- The difference between class attributes and instance attributes
- The special
selfparameter - Common patterns and beginner mistakes
Attributes: Data Inside Objects
An attribute is a value stored inside an object (or class). You can think of attributes as “variables that belong to an object”.
When you have a class, each object (instance) created from that class can have its own attribute values.
class Person:
def __init__(self, name, age):
# These are attributes
self.name = name
self.age = age
# Create two different Person objects
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
print(person1.name) # Alice
print(person2.name) # BobHere:
nameandageare attributes of eachPersonobject.person1andperson2each have their ownnameandage.
Instance Attributes
Instance attributes belong to a specific object (instance) of a class.
Typical pattern:
- Defined (or at least initialized) inside
__init__ - Use
self.attribute_nameto create and access them
class Car:
def __init__(self, brand, year):
self.brand = brand # instance attribute
self.year = year # instance attribute
my_car = Car("Toyota", 2020)
your_car = Car("Honda", 2018)
print(my_car.brand) # Toyota
print(your_car.brand) # HondaYou can also add a new attribute to an instance after it is created, but this can make code harder to understand if overused:
my_car.color = "red"
print(my_car.color) # red
# your_car.color would cause an error (AttributeError) if not set
Beginners usually define attributes in __init__ so that all instances start with the same set of attributes.
Class Attributes
A class attribute is shared by all instances of the class, unless overridden on a particular instance.
Class attributes are defined directly inside the class, but outside any method.
class Dog:
species = "Canis familiaris" # class attribute (shared)
def __init__(self, name):
self.name = name # instance attribute
dog1 = Dog("Fido")
dog2 = Dog("Rex")
print(dog1.name) # Fido (instance-specific)
print(dog2.name) # Rex (instance-specific)
print(dog1.species) # Canis familiaris (class attribute)
print(dog2.species) # Canis familiaris
print(Dog.species) # Canis familiarisIf you change the class attribute on the class, all instances see the new value (unless they have their own attribute with the same name):
Dog.species = "Canis lupus familiaris"
print(dog1.species) # Canis lupus familiaris
print(dog2.species) # Canis lupus familiarisIf you assign to the attribute on an instance, you create/overwrite an instance attribute with that name, which hides the class attribute for that object:
dog1.species = "Mutant dog"
print(dog1.species) # Mutant dog (instance attribute)
print(dog2.species) # Canis lupus familiaris (class attribute)
print(Dog.species) # Canis lupus familiarisSummary:
- Use instance attributes (
self.something) for data that is different per object. - Use class attributes for data that is usually the same for all objects of that class.
Methods: Functions Inside Classes
A method is a function defined inside a class. Methods describe what an object can do.
When you call a method on an object, Python automatically passes that object as the first argument to the method.
class Counter:
def __init__(self):
self.value = 0 # instance attribute
# This is a method
def increment(self):
self.value += 1
counter = Counter()
counter.increment()
counter.increment()
print(counter.value) # 2Here:
incrementis a method.- It changes the
valueattribute of the specificcounterobject.
The `self` Parameter
Inside a class, most methods have self as their first parameter.
selfrefers to the specific instance the method was called on.- You use
selfto access attributes and other methods of the same object.
You don’t pass self explicitly when calling the method; Python does it for you.
class Person:
def __init__(self, name):
self.name = name
def greet(self): # self is the instance
print("Hello, I am", self.name)
p = Person("Alice")
# Behind the scenes, Python turns this:
p.greet()
# into this:
Person.greet(p)Rules to remember:
- Always include
selfas the first parameter of instance methods. - Always use
self.attributeandself.method_name()inside the class to refer to the current object’s data and behavior.
Methods That Use Attributes
Methods often read or change the object’s attributes.
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount # change attribute
print("New balance:", self.balance)
def display_info(self):
print("Owner:", self.owner)
print("Balance:", self.balance)
account = BankAccount("Sam", 100)
account.deposit(50) # New balance: 150
account.display_info()Here:
depositanddisplay_infoare methods.- They work with
self.balanceandself.owner, which are attributes.
Methods vs Functions
Both methods and functions use def, but:
- A function is defined outside any class.
- A method is defined inside a class and usually has
selfas its first parameter.
# A normal function
def add(a, b):
return a + b
class Calculator:
# A method
def add(self, a, b):
return a + b
calc = Calculator()
print(add(2, 3)) # function call
print(calc.add(2, 3)) # method call on an objectClass Methods and Static Methods (Intro)
Besides regular (instance) methods, Python also allows:
- Class methods – methods that work with the class itself
- Static methods – methods that don’t need the instance or the class
Basic idea:
- Use
@classmethodand@staticmethoddecorators. - These are more advanced and used less often for beginners, but you’ll see them in real code.
class Example:
counter = 0
def __init__(self):
Example.counter += 1
@classmethod
def how_many(cls): # cls refers to the class
return cls.counter
@staticmethod
def say_hello():
print("Hello from static method")
e1 = Example()
e2 = Example()
print(Example.how_many()) # 2
Example.say_hello() # Hello from static method
For now, focus mainly on instance methods (with self), but be aware that these other kinds exist.
Combining Attributes and Methods
Attributes and methods work together to model things that have both data and behavior.
Example: a simple Rectangle class.
class Rectangle:
def __init__(self, width, height):
self.width = width # attributes
self.height = height
def area(self): # method using attributes
return self.width * self.height
def perimeter(self): # another method
return 2 * (self.width + self.height)
rect = Rectangle(3, 4)
print(rect.area()) # 12
print(rect.perimeter()) # 14
The object rect:
- Has data:
width,height - Can do things:
area(),perimeter()
Updating Attributes with Methods
A common pattern is to provide methods that safely update attributes.
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
def to_fahrenheit(self):
return self.celsius * 9/5 + 32
def set_celsius(self, new_value):
self.celsius = new_value
t = Temperature(20)
print(t.to_fahrenheit()) # 68.0
t.set_celsius(30)
print(t.to_fahrenheit()) # 86.0
Instead of changing attributes directly from outside, you can change them with methods (set_celsius). This can make it easier to control or validate changes later.
Common Beginner Mistakes with Attributes and Methods
1. Forgetting `self` in Method Definitions
class Person:
def greet(): # Missing self
print("Hello")
This will cause an error when you try to call Person().greet(). Correct:
class Person:
def greet(self):
print("Hello")2. Forgetting to Use `self` When Accessing Attributes
class Person:
def __init__(self, name):
name = name # Wrong: not stored on the instanceThis just assigns the parameter to a local variable, then throws it away.
Correct:
class Person:
def __init__(self, name):
self.name = name # Correct: store on the instance3. Using Class Attributes Instead of Instance Attributes by Accident
class Counter:
value = 0 # class attribute
def increment(self):
self.value += 1This technically works, but it can behave in confusing ways because you’re mixing class and instance attributes. Better:
class Counter:
def __init__(self):
self.value = 0 # instance attribute
def increment(self):
self.value += 14. Calling Methods on the Class Instead of an Instance (or Vice Versa)
class Greeter:
def say_hello(self):
print("Hello")
Greeter.say_hello() # Error: missing selfYou need an instance:
g = Greeter()
g.say_hello() # OKPractice Ideas
To get comfortable with attributes and methods, try:
- A
Bookclass with attributes liketitle,author,pages, and methodssummary()(prints a short text) andis_long()(returnsTrueif more than 300 pages). - A
Pointclass withxandyand methodsmove(dx, dy)to change the coordinates anddistance_to_origin()to compute the distance from $(0, 0)$. - A
Timerclass with methods tostart(),stop(), and an attribute forelapsed_time(you can simulate time with simple counters at first).
Focus on:
- Storing data in attributes (
self.attribute) - Using methods to read and change those attributes
- Understanding how each instance has its own attribute values