Concepts / Designing Classes for Real-World Problems

Designing Classes for Real-World Problems

A class is a template that defines what data and code each object will have; the class keyword does not create an object.

  • Programming

A Template Is Not an Object

When you design a class, you describe the data and code that objects of that class will have. The class is a template, not an object. Writing the class keyword defines that template, but it does not by itself create an object. An object is created when the class is called as if it were a function.

createscreatesPartyAnimaltemplateanx = 0anotherx = 0
What is the difference between a class template and the individual objects created from it?

A useful analogy is a cookie cutter. The cutter describes the shape shared by the cookies, but the cutter is not itself a cookie. In the same way, a class describes the structure and behavior that its objects will have, while each object is an individual instance created from that template.

Creating an Initialized Object

Calling a class creates a new object. During that creation, Python automatically runs the object's __init__ method. The purpose of __init__ is to set up the object's initial attributes, giving the object its starting data. In the PartyAnimal example, creating an object sets its x attribute to 0.

callrunssetsPartyAnimalclass templatePartyAnimal()class call__init__automatic callx0
What happens to an object's attributes when the object is created?

class PartyAnimal: def __init__(self): self.x = 0 def party(self): self.x = self.x + 1 print(self.x) an = PartyAnimal()

Following self Through a Method Call

The self parameter refers to the specific object on which a method was called. It lets the method access and modify that object's attributes. In the expression an.party(), self refers to an. Therefore, self.x means the x attribute belonging to an, rather than an attribute belonging to some other object.

callsuses selfupdatesanx = 0party()self = anself.xreads an.xx = 1an.x
How does self connect a method call to the specific object whose attributes the method reads or changes?

What do you think happens?

After an = PartyAnimal(), what will an.x be after three calls to an.party()?

  • 0
  • 1
  • 3
  • The class itself changes, but an.x does not
Reveal answer

Answer: 3

The object starts with x equal to 0. Each call to party uses self to increase that object's x by 1, so three calls produce x equal to 3.

Output
0
1
2
3

Designing Shared Behavior

Designing a class means deciding what data belongs to each object and what actions should operate on that data. The class holds the shared design for those attributes and methods. Each object created from the class has its own independent attribute data, while the methods provide reusable behavior for working with that data.

definesdefinesproducesPartyAnimalentity typexattributeobjectsindividual instancespartymethod
How are a real-world entity's shared data and behaviors translated into a class?

Put behavior that operates on an object's own data into methods, and use self when those methods need to read or modify that data. This keeps one class definition reusable for as many objects as the problem requires.

Independent Object State

One class can produce many objects with the same structure but independent attribute data. If two objects are created from PartyAnimal, each begins with its own x value initialized by __init__. When a method uses self to change one object's x, it operates on the object connected to that method call.

createscreatesPartyAnimalshared templateanx = 1anotherx = 0
How can one class produce multiple independent objects with the same structure but different attribute values?
python
Output
After the call, an.x is 1 and another.x remains 0.

Mistakes Beginners Make

  • Treating the class definition as an object

    The class keyword defines a template. It does not create an object.

    Fix: Call the class, as in an = PartyAnimal(), to create an object.

  • Ignoring the role of __init__

    __init__ runs automatically when the object is created and sets up its initial attributes.

    Fix: Use __init__ to establish the object's starting data.

  • Using an object's data without self

    self identifies the particular object whose attribute the method should access or modify.

    Fix: Use self.x when the method needs the object's x attribute.

  • Assuming one object's method changes every object's data

    self is bound to the object on which the method was called.

    Fix: Track the object before the dot in the method call; an.party() operates on an.

Practice the Trace

EASY

Consider a PartyAnimal object that starts with x equal to 0. Trace the value of x after each of these calls: an.party(), an.party(), an.party(). Then explain which object self refers to during each call.

Hints
  • The object is initialized with x equal to 0.
  • Each party method call increases the selected object's x by 1.
  • In an.party(), self refers to an.

Tracing Three Method Calls

Determine the value of an.x after an = PartyAnimal() followed by three calls to an.party().

Create the object: Calling PartyAnimal creates an object and automatically runs __init__, which sets an.x to 0.

First call: In an.party(), self refers to an. The method increases an.x from 0 to 1.

Second call: self still refers to an, so the method increases an.x from 1 to 2.

Third call: The same method changes the same object's attribute from 2 to 3.

After three calls, an.x is 3.

Key Takeaways

  • A class is a template that defines the data and code its objects will have; it is not itself an object.
  • Calling a class creates an object, and __init__ runs automatically to initialize that object's attributes.
  • The self parameter refers to the specific object on which a method was called.
  • Methods use self to read and modify the correct object's attributes.
  • One class can create many objects with the same structure and independent data.