sec04 - Python Classes for Beginners: Understanding Instances, self, and init Clearly
スポンサーリンク

What Is a Class?

In Python, a class is a blueprint for creating objects.

For example, suppose you want to create a program that handles cars. If you only need to deal with a single car, you can manage its color or speed as fixed values. However, if you want to manage multiple cars at once, each car should have its own color and speed. This is where classes come in.

By using a class, you can define the common structure (the blueprint, or class) of a car, and then create multiple instances (objects) from it. These instances are also called instance objects or simply objects.

Minimal Class Definition and Naming Rules

Let’s start by looking at the simplest example of a class definition.

class Car:
    pass  # Nothing inside yet

Explanation:

  • class Car: — Defines a class.
    • class: The keyword used to define a class.
    • Car: The name of the class.
      • The naming rules are the same as for variables, but in Python, it is recommended to write class names in UpperCamelCase. This means each word starts with an uppercase letter and words are joined without underscores (_). (Reference: Python: PEP8, CamelCase (wiki))
    • :: Don’t forget the colon at the end of the class definition line.
  • pass: A statement that does nothing but is recognized as valid syntax. It is used here because we haven’t written any logic yet.

When you run the code above, nothing happens yet because we have only defined a blueprint that doesn’t contain any behavior.

スポンサーリンク

What Is Instantiation? Creating Objects from a Class

In the following code, we define a class called Car and create an instance named my_car from it.

class Car:
    pass  # Nothing inside yet

my_car = Car()
print(my_car)

Explanation:

  • Car(): Creates an instance (object) from the class.
  • my_car: A variable that stores the created object.
  • print(my_car): Confirms that the instance exists in memory.

Example output:

<__main__.Car object at 0x000001D580F94590>

This indicates that “an object created from the Car class exists in memory.” It doesn’t have any functionality yet, but you have successfully created a car object based on the Car blueprint.

(Note: The memory address part varies depending on your environment.)

The Relationship Between Classes and Instances

A class itself is just a blueprint; it doesn’t do anything on its own. To actually use it, you must instantiate it to create a concrete object.

By adding parentheses () after a class name, Python performs the instantiation process.

Car (class) ──▶ Car() ──▶ Instance (actual car)

In this way, executing Car() creates a real car object based on the structure defined by the class.

class Car:
    def __init__(self):
        print('Created a car!')

car1 = Car()
car2 = Car()
Created a car!
Created a car!

Each time Car() is called, a special method called __init__ (explained later) runs, creating a new car (instance). Even though they share the same blueprint, car1 and car2 are independent cars.

init Method and self: Assigning Data to Objects via Instance Variables

The __init__ method is a special method that is automatically called when an instance is created. You can use it to perform initialization tasks.

What Is a Method?

A method is similar to a function, but there are key differences:

  • Method
    • Defines operations related to an object and is bound to an instance.
  • Function
    • A collection of code that performs a specific task and exists independently of any instance.

Although there are technical differences, both group together related processing logic. You don’t need to worry too much about the distinction when writing code.

self refers to the instance itself. It must always be the first parameter of a method and is used when accessing or modifying instance variables.

In the following example, a car created with Car('red') is recorded as a “red car.” By writing self.color, you attach a variable color to that particular instance. Each instance stores its own values independently.

class Car:
    def __init__(self, color):  # Receives the value passed when creating the instance
        self.color = color  # Stores the value in an instance variable

car1 = Car('red')
car2 = Car('blue')

print(car1.color)  # red
print(car2.color)  # blue

Code explanation:

  • __init__
    • The initialization method automatically called once when an instance is created.
    • When you create an instance like Car('red'), the value is passed to __init__. The first parameter receives the instance itself (commonly named self), so the arguments you pass when creating the instance are handled as the second and subsequent parameters.
  • self
    • Refers to the instance itself.
  • self.color = color
    • Assigns the argument value to an instance variable.
    • The local variable color disappears after the method ends (like in a normal function). However, assigning it to self.color ensures the value remains stored as long as the instance exists.
[Flow of Execution]

Create Car('red')
         │
         ▼
  __init__(self, color)
         │
   self ← my_car  (this instance itself)
   color ← 'red'  (passed value)
         │
         ▼
  Set self.color to 'red'

Defining Behavior with Instance Methods

Next, let’s give the car not only data (attributes) but also behavior (methods). We’ll implement an accelerate method. By calling car.accelerate(), you can make the car accelerate.

class Car:
    def __init__(self, color):
        self.color = color     # Initialize instance variable color
        self.speed = 0         # Initialize instance variable speed (default 0)

    def accelerate(self):
        # Increase self.speed
        self.speed += 10
        # Display current speed with an f-string
        print(f'The {self.color} car accelerated. Current speed: {self.speed}km/h')

car = Car('red')
car.accelerate()   # Call instance method
car.accelerate()
print('Final speed:', car.speed)

Example output:

The red car accelerated. Current speed: 10km/h
The red car accelerated. Current speed: 20km/h
Final speed: 20

Explanation of key points:

  • self.speed = 0
    • Initializes speed as an instance variable (each instance has its own speed).
  • def accelerate(self):
    • accelerate is an instance method. It accesses attributes via self.
  • self.speed += 10
    • Increases the speed by 10 (a simple acceleration logic).
  • car.accelerate()
    • Called in the form instance.method().
    • When called, self refers to the instance (car in this case).

Flexible Initialization with Default Arguments

By setting default values for parameters, you can create instances without passing arguments.

class Car:
    def __init__(self, color='white'):
        self.color = color
        self.speed = 0

car_default = Car()       # color omitted → default 'white'
car_green = Car('green')  # color specified

print(car_default.color)  # Output: white
print(car_green.color)    # Output: green

Example output:

white
green

Let's Customize the Car Class

Let's further customize the Car class. We’ll set default arguments for the acceleration and braking methods, and add a method that returns the current status.

  • By giving the class multiple attributes such as model="sedan", the design becomes closer to a real-world scenario.
  • The status method returns a dictionary, making it easy to handle the state externally.
  • The accelerate and brake methods can accept an argument to specify the change in speed, providing flexible behavior.
class Car:
    # Constructor (the process that runs when an instance is created)
    def __init__(self, color='white', model='sedan'):
        # Instance variables: data that each instance holds independently
        self.color = color      # Car color
        self.model = model      # Car model
        self.speed = 0          # Current speed (km/h) - initial value 0

    # Instance method: accelerate
    def accelerate(self, value=10):
        # Increase speed by the value
        self.speed += value
        print(f'The {self.color} {self.model} accelerated. Current speed: {self.speed} km/h')

    # Instance method: brake (decelerate)
    def brake(self, value=10):
        # Ensure the speed does not fall below 0 using max
        self.speed = max(0, self.speed - value)
        print(f'The {self.color} {self.model} slowed down. Current speed: {self.speed} km/h')

    # Instance method: display status (return information)
    def status(self):
        return {'color': self.color, 'model': self.model, 'speed': self.speed}

# Example usage
car_a = Car('red', 'coupe')
car_b = Car('blue')  # model defaults to 'sedan'

car_a.accelerate(30)
car_a.brake(15)
print('car_a status:', car_a.status())

car_b.accelerate()
print('car_b status:', car_b.status())

Example Output:

The red coupe accelerated. Current speed: 30 km/h
The red coupe slowed down. Current speed: 15 km/h
car_a status: {'color': 'red', 'model': 'coupe', 'speed': 15}
The blue sedan accelerated. Current speed: 10 km/h
car_b status: {'color': 'blue', 'model': 'sedan', 'speed': 10}

Another important point here is that instances created from the same class are independent of each other. The color, model, and current speed of car_a and car_b are all different.

Common Questions & Answers: Understanding self and init

Q1. Is self a keyword? Can I omit it?

A1. self is not a reserved keyword in the Python language, but it is used by convention. The first parameter of a method is intended to receive the instance itself, so using self is the standard. Technically, other names will work, but it would confuse readers. Always use self for clarity and consistency.

Also, if you forget to include self in the method definition (for example, writing def accelerate():), calling it from an instance will cause an error (TypeError: Car.accelerate() takes 0 positional arguments but 1 was given). Always include self as the first parameter.

Q2. What’s the difference between Car() and Car?

A2. Car is a class object (the blueprint), while Car() is a call that creates an instance from that class. When you add () to Car, an instance is created, and the __init__ method is called.

Q3. What happens if I don’t define __init__?

A3. If you don’t define __init__, Python performs a default empty initialization (it does nothing). You can still create an instance, but if you want to set attributes during initialization, you need to define __init__.

スポンサーリンク