An object is a data structure (state) with a set of functions specific to the object that give a different result depending on the state of the object (its attributes).
Introduction
Object-oriented programming was born with Simula in 1962, and its origin is to simulate objects and interactions between objects.
An object is a data structure (state) with a set of functions specific to the object that give a different result depending on the state of the object (its attributes).
Finally, remember that object-oriented programming is invaluable in creating user interfaces, real object simulation programs (such as 3D design), etc., but not in managing processes that process data such as artificial intelligence, web services, etc.
Object
Data structure
Every programming language is composed of simple data structures that allow you to represent anything, for example, a rectangle:
rectangle_length = 3rectangle_width = 6But if we have two rectangles, how can we represent them?
rectangle_a_length = 3rectangle_a_width = 6
rectangle_b_length = 5rectangle_b_width = 10It’s not a good solution. What if we use a list?
rectangle_a = [3, 6]rectangle_b = [5, 10]In this way, we have the properties of a rectangle grouped in a single data structure under a single reference.
Functions
What if we want to calculate the area of a rectangle?

def rectangle_area(length, width): return length * width
def test(): assert rectangle_area(3, 4) == 12Let’s test if it works.
We create a new project:
uv init testcd testuv add --dev pytestWe install the pytest dependency in a development environment since we don’t need it in a production environment (—group dev).
We can now run pytest:
uv run pytestBut didn’t we say we were using a list to represent a rectangle?
def rectangle_area(rect): return rect[0] * rect[1]
def test(): rectangle = [3, 6] assert rectangle_area(rectangle) == 18We have a function that calculates the area of a rectangle… only if the list it receives as a parameter represents a rectangle.
The truth is that in somewhat complex code many unforeseen things can happen, because you can say that a list of two values is a rectangle, but for Python it’s just a list.
def rectangle_area(rect): return rect[0] * rect[1]
def test():
rectangle = [3, 6] assert rectangle_area(rectangle) == 18
triangle = [3, 6] # base, height assert rectangle_area(triangle) == 9And it might seem obvious because it’s only a few lines, but after a hundred it’s not fun at all.

Classes
That’s why classes exist in Python:
class Rectangle: def __init__(self, length, width): self.length = length self.width = width
def rectangle_area(rect): return rect.length * rect.width
def test():
# a cube is not a rectangle rectangle = Rectangle(3, 6) assert rectangle_area(rectangle) == 18
triangle = [3, 6] # base, height assert rectangle_area(triangle) == 9$ pytest test.pyrect = [3, 6] def rectangle_area(rect):> return rect.length * rect.widthE AttributeError: 'list' object has no attribute 'length'Python uses duck typing. Therefore, the rectangle_area function accepts any object that has two attributes named length and width.
class Rectangle: def __init__(self, length, width): self.length = length self.width = width
class Cube: def __init__(self, length, width, height): self.length = length self.width = width self.height = height
def rectangle_area(rect): return rect.length * rect.width
def test():
# a cube is not a rectangle rectangle = Rectangle(3, 6) assert rectangle_area(rectangle) == 18
cube = Cube(3, 6, 2) assert rectangle_area(cube) == 36Since a cube has the attributes length and width, the rectangle_area function has no problem calculating its area:
When I see a bird that walks like a duck, swims like a duck, and sounds like a duck, I call that bird a duck.
Languages that force you to declare the parameter type do not have this problem.
We can modify the rectangle_area function to verify that the parameter is an instance of the Rectangle class with the isinstance function:
class Rectangle: def __init__(self, length, width): self.length = length self.width = width
class Cube: def __init__(self, length, width, height): self.length = length self.width = width self.height = height
def rectangle_area(rect): assert isinstance(rect, Rectangle) return rect.length * rect.width
def test():
rectangle = Rectangle(3, 6) assert rectangle_area(rectangle) == 18
cube = Cube(3, 6, 2) assert rectangle_area(cube) == 36Now, instead of giving us erroneous data, the function generates a runtime error (in languages like Java the error would be at compile time).
Anyway, if the rectangle_area function should only work with objects of the Rectangle class, why not put it all together?
class Rectangle: def __init__(self, length, width): self.length = length self.width = width
def area(self): return self.length * self.width
def test():
rectangle = Rectangle(3, 6)
assert rectangle.length == 3 assert rectangle.area() == 18By the way, in UML the Rectangle class is represented like this:
To facilitate the creation of diagrams, you can use our guide to use the Mermaid plugin in VSCode.
Exercises
Below is a UML representation of classes, and you must write the corresponding Python code.
Equilateral triangle
class Triangle: def __init__(self, base, height): self.base = base self.height = height
def area(self): return self.base * self.heightButton
Let’s represent a button in a graphical interface:
And its Python coding would be this:
class Button: def __init__(self, active, message): self.active = active self.message = message
def click(self): if self.active: return self.message else: return ""Window
One of the main characteristics of object-oriented programming is object composition.
For example, a window of a graphical interface can have a button:
And its Python coding would be this:
class Window: def __init__(self, title, width, height, content, button): self.title = title self.width = width self.height = height self.content = content self.button = button
def resize(self, width, height): self.width = width self.height = heightWe can create an instance of Window and verify its operation:
def test():
window = Window("DAW", 600, 300, "Some content", Button(True, "hello"))
message = window.button.click() assert message == "hello"
window.button.active = False message = window.button.click() assert message == ""
window.resize(200, 400) assert window.width == 200 assert window.height == 400Inheritance
TODO