Modeling Systems

Defining Classes and Creating Objects


Learning Objectives

  • You can distinguish a class, an instance, and an attribute.
  • You can define __init__ to establish an instance’s initial state.
  • You can explain how self refers to the object being initialized.
  • You can distinguish independent instances from aliases of one instance.

A list has state and operations that use that state:

scores = [10, 20]
scores.append(30)

The list object holds the items. Its append method changes that object’s contents. A class lets us define a new type whose instances have their own state and methods.

Start with One Small Object

No files opened Select a file to edit

This prints 5.

class Counter: defines a class named Counter. Calling Counter(5) creates an instance, an individual object of that class.

Calling a class to create an instance is also called a constructor call. Python then runs the class’s initializer, __init__, to set up the new instance. The spelling has two underscores before and after init. It is a special method name recognized by Python.

Inside that call, self refers to the new counter and start refers to 5. Assignment creates an instance attribute:

self.value = start

An attribute is named information reached through an object. Outside the method, counter.value reaches the same attribute.

self Identifies the Current Instance

The definition header def __init__(self, start): names two parameters, self and start, but the class call supplies one explicit argument:

Counter(5)

Python supplies the instance as the first argument of this initialization method. The remaining argument is bound to start.

self is the conventional name for that first parameter. It is not a global variable containing every object, and it is not a separate copy of the instance. Use the conventional name so other Python readers can recognize its role.

Each Instance Has Its Own Attributes

Predict the three printed values. Which assignment creates another object, and which gives an existing object another name?

No files opened Select a file to edit

Step through the same program. During each initializer call, follow self to the new instance. Then watch what happens to the arrows when other = first runs.

Code

Step 1 of 13

1 / 13
Formatting...

State

main

No variables

Objects

No objects yet

Output

No output yet

The two class calls create separate instances. The assignment other = first creates an alias, as in Part 3. The labels C1 and C2 identify the instances in the visualization; they are not names in the Python program.

The output is 9, 20, and 9. In the editor, change other = first to other = Counter(5) and predict the output again before running it.

Represent an Equipment Item

An equipment item from the catalogue needs several attributes:

No files opened Select a file to edit

This version assumes valid nonempty strings. The next chapter adds validation and borrowing operations.

The identifier is stored in item_id; it plays the same role as the dictionary’s "id" field. Attributes do not have to have exactly the same names as fields in an external file.

The boolean available belongs to each item. The code does not need separate variables such as camera_available and tripod_available scattered through the program.

Local Names and Attributes Are Different

Inside __init__, name and self.name are not interchangeable:

self.name = name

The right side reads the local parameter. The left side stores an attribute on the instance. After initialization finishes, the local call has ended, but the attribute remains reachable through the object.

Writing only:

name = name

would not create an instance attribute. A later camera.name lookup would then fail because no such attribute had been established.

__init__ initializes an object; it should not return that object. The class call produces the instance. A successful __init__ finishes without returning a non-None value.

Use the supplied check.py to test the class in each programming exercise. It imports your class from main.py, creates instances, and checks their attributes. Open Show file tree, select check.py, and Run. Extend those checks with a second instance. Keep main.py focused on definitions so importing it does not print or ask for input.

Create study sessions

0 / 10 points

Define StudySession(subject, minutes) in main.py. Its initializer stores the supplied subject string and positive integer minutes in attributes with those names. Store the subject exactly as supplied, including whitespace; an empty string is allowed. Inputs are valid in this exercise. Do not print or read input. No additional methods are required. Separate constructor calls must create independent instances, even when their initial values match. Assigning another name to an existing session must still refer to that session.

Work in main.py. Open Show file tree, select check.py, and Run to check small instances and their independence. Extend these sample checks with your own cases. Submit sends the files to the grader, which imports your definitions and tries additional cases. Keep main.py free of test calls, printing, and input.

Compare local names, attributes, and aliases in the following review before repairing an initializer yourself.

Now diagnose an initializer that uses local names where instance attributes are needed. Check both the initial values and whether two objects remain independent.

Repair a reading goal

0 / 10 points

Repair the ReadingGoal class. ReadingGoal(label, target) receives a label string and a nonnegative integer target. Each instance must have label and target attributes containing those values, and a pages attribute initially zero. Store the label exactly as supplied, including whitespace; an empty string is allowed. Inputs are valid. Changing an attribute of one goal must not affect a separately created goal. Do not print or add input. Inspect whether the supplied initializer establishes the promised attributes.

Work in main.py. Open Show file tree, select check.py, and Run to check small instances and their independence. Extend these sample checks with your own cases. Submit sends the files to the grader, which imports your definitions and tries additional cases. Keep main.py free of test calls, printing, and input.

Check Your Understanding

  1. What is the difference between a class and one of its instances?
  2. Which argument does Python supply as self during initialization?
  3. How does self.name differ from a local parameter named name?
  4. Why does other = first not create another instance?
  5. Why should __init__ not return the instance itself?