Python Classes and Objects CL-21

Python Classes and Objects


Introduction to Classes and Objects

Imagine you're building a house. Before you start, you need a blueprint, a plan that shows how the house should look and what rooms it should have. In programming, a class is like that blueprint. It's a plan for creating objects.

Now, think of the actual house that gets built from the blueprint. It has rooms, furniture, and all the things that make it a real house. In programming, objects are like the real houses. They are created based on the blueprint (class) and can store data (like the color of the walls) and behavior (like the door opening).

Example:
Let's say we want to create a class for cars. This class would be our blueprint for creating different cars.
python
class Car: # This is the blueprint for a Car class def __init__(self, make, model): self.make = make self.model = model def start_engine(self): return f"The {self.make} {self.model}'s engine is running." # Now, let's create an actual car (an object) my_car = Car("Toyota", "Camry") # We've created an object based on the Car class blueprint. # We can access its data and behavior. print(f"My car is a {my_car.make} {my_car.model}.") print(my_car.start_engine())

Output:
swift
My car is a Toyota Camry. The Toyota Camry's engine is running.

In this example, we introduced the concept of classes and objects by comparing them to blueprints and real objects (houses and cars). We created a simple Car class and used it to create an object (my_car) that could store data (make and model) and exhibit behavior (starting the engine).


Declaring a Class in Python

To create a class in Python, you use the class keyword. Think of a class as a recipe for creating objects with specific characteristics and behaviors.

Example:
Let's say we want to create a class for representing dogs.
python
# Here's how we declare a class using the 'class' keyword. class Dog: # This is the class for representing dogs. pass # Now, we've created the Dog class. It's like a blueprint for making dogs.

Output:
There's no output here because we've only declared the class. We haven't created any dog objects yet.


Naming Conventions for Class Names (CamelCase)

Class names in Python usually follow a naming convention called "CamelCase." This means that you write the first letter of each word in the name with a capital letter, and there are no spaces between words. It looks like the humps of a camel.

Example:
Here's how you apply CamelCase to name your Dog class:
python
# Using CamelCase for the class name class DogBreed: # This is the class for representing dogs. pass

Notice that we write "DogBreed" with a capital "D." This makes it easy to distinguish class names from variable names in your code.

In Python, it's a good practice to follow these naming conventions because it makes your code more readable and consistent. It's like a common language that Python programmers use to communicate and understand each other's code better.


Attributes (Properties):

In everyday life, you can think of attributes as characteristics or properties that define an object. For example, a car has attributes like its color, make, and model. Similarly, in programming, attributes (also known as properties or member variables) are pieces of information that describe an object or its state.

Demonstrating How to Define Attributes:

To define attributes within a class, you use variables. These variables hold the data that represents the object's characteristics. In Python, you define attributes inside the class using the self keyword.

Example:
Let's create a Person class with attributes like name and age:
python
class Person: def __init__(self, name, age): # 'name' and 'age' are attributes defined within the class. self.name = name self.age = age # Now, let's create a person object and assign values to its attributes. alice = Person("Alice", 30) bob = Person("Bob", 25) # We've created two person objects, each with their own name and age attributes.

Output:
There is no direct output because we're defining the class and creating objects. The attributes are stored inside the objects.


Instance Attributes vs. Class Attributes:

Instance Attributes:
  • Instance attributes belong to a specific instance (object) of a class.
  • Each object can have different values for its instance attributes.
  • In the above example, name and age are instance attributes because they are unique to each person.
Class Attributes:
  • Class attributes are shared among all instances of a class.
  • They are defined outside of any method and are the same for all objects created from the class.
  • Class attributes are useful for storing data that is common to all objects of that class.
Example:
Let's add a class attribute to the Person class to represent a common species attribute for all people:
python
class Person: # This is a class attribute, shared by all instances of the class. species = "Homo sapiens" def __init__(self, name, age): # 'name' and 'age' are instance attributes. self.name = name self.age = age # Now, let's create person objects and access the class attribute. alice = Person("Alice", 30) bob = Person("Bob", 25) # Accessing instance attributes print(f"{alice.name} is {alice.age} years old.") print(f"{bob.name} is {bob.age} years old.") # Accessing the class attribute print(f"All people belong to the {alice.species} species.")

Output:
vbnet
Alice is 30 years old. Bob is 25 years old. All people belong to the Homo sapiens species.

In this example, species is a class attribute shared by all instances of the Person class, while name and age are instance attributes specific to each person object.


Methods:

Methods in programming are like actions or behaviors associated with an object. Think of them as things an object can do. Just like people can walk, talk, or eat, objects in programming can have methods to perform various tasks. These methods are defined within a class, and they allow objects to interact with their data or the outside world.

Explaining How Methods Define Behavior:

Methods define the behaviors or actions an object can take. They allow you to package functionality within an object so that you can perform specific operations on it. For example, a Car object might have methods like start_engine or stop_engine to define how the car behaves when you want to start or stop it.

Example:
Let's continue with our Person class and add a method called say_hello to make a person say hello:
python
class Person: def __init__(self, name, age): self.name = name self.age = age def say_hello(self): # This is a method that defines the behavior of saying hello. return f"Hello, my name is {self.name}." # Now, let's create a person object and use the 'say_hello' method. alice = Person("Alice", 30) # Calling the 'say_hello' method greeting = alice.say_hello() print(greeting)

Output:
csharp
Hello, my name is Alice.

In this example, we introduced the concept of methods as behaviors associated with objects. The say_hello method was defined within the Person class to allow a person object to say hello when the method is called.

Methods are powerful because they encapsulate behavior within objects, making code more organized and reusable. Different objects of the same class can use the same methods to perform their specific tasks, just like how people of the same species can perform similar actions.



Accessing Attributes and Methods with Dot Notation:

In programming, you can access an object's attributes (properties) and methods using dot notation. It's like using a "dot" to tell the object to do something or provide information. Think of it as asking an object about itself or telling it to perform a task.

Accessing and Modifying Attributes:

Attributes are like the characteristics of an object, such as a person's name or age. To access them, you use dot notation. You can also modify attributes by assigning new values using dot notation.

Example:
Let's use our Person class to show how to access and modify attributes:
python
class Person: def __init__(self, name, age): self.name = name self.age = age def say_hello(self): return f"Hello, my name is {self.name}." # Create a person object alice = Person("Alice", 30) # Accessing attributes using dot notation print(f"Name: {alice.name}") print(f"Age: {alice.age}") # Modifying an attribute alice.age = 31 print(f"Updated Age: {alice.age}")

Output:
yaml
Name: Alice Age: 30 Updated Age: 31


In this example, we accessed the name and age attributes of the alice object using dot notation. Later, we modified the age attribute by assigning a new value.

Calling Methods on Objects:

Methods are like actions or behaviors that objects can perform. To call a method on an object, you also use dot notation.

Example:
Let's use our Person class's say_hello method to make Alice say hello:
python
class Person: def __init__(self, name, age): self.name = name self.age = age def say_hello(self): return f"Hello, my name is {self.name}." # Create a person object alice = Person("Alice", 30) # Calling the 'say_hello' method using dot notation greeting = alice.say_hello() print(greeting)

Output:
csharp
Hello, my name is Alice.

In this example, we called the say_hello method on the alice object using dot notation, and it returned a greeting.

Dot notation is fundamental in programming because it allows you to interact with objects by accessing their data (attributes) and behavior (methods) in a clear and organized way.


Class Variables:

In programming, class variables are like shared information that's common to all instances (objects) of a class. Think of them as properties that every object of that class can access and use. These variables are defined at the class level, and their values are the same for every instance of that class.

Defining and Using Class Variables:

To define a class variable, you declare it within the class but outside any methods. You can access class variables using the class name or any instance of the class.

Example:
Let's use a Car class to demonstrate class variables. We'll define a class variable called total_cars to keep track of the total number of cars created.
python
class Car: # This is a class variable, shared among all car instances. total_cars = 0 def __init__(self, make, model): self.make = make self.model = model # Increase the total_cars count when a new car is created. Car.total_cars += 1 # Create car objects car1 = Car("Toyota", "Camry") car2 = Car("Honda", "Civic") # Accessing the class variable 'total_cars' using the class name print(f"Total cars created: {Car.total_cars}") # You can also access it using an instance (not recommended for class variables) print(f"Total cars created (using instance): {car1.total_cars}")

Output:
mathematica
Total cars created: 2 Total cars created (using instance): 2

In this example, we defined a class variable total_cars within the Car class. Every time a new car object is created (through the __init__ method), we increase the total_cars count. All instances of the Car class share this total_cars class variable.

Difference Between Class Variables and Instance Variables:

Class Variables:
  • Shared among all instances of the class.
  • Defined at the class level but outside any methods.
  • Used when data should be common to all objects of that class.
  • Accessed using the class name or instances (though it's typically accessed using the class name for clarity).
Instance Variables:
  • Specific to each instance of the class.
  • Defined inside the constructor (__init__) or other methods.
  • Used when data needs to be unique or specific to each object.
  • Accessed using the instance name (object name).
In summary, class variables provide a way to store data that is shared among all instances of a class, while instance variables allow you to store data unique to each object.


Special Methods (Magic or Dunder Methods):

Special methods, often called "magic" or "dunder" methods (short for "double underscore"), are a set of predefined methods in Python. They have double underscores at the beginning and end of their names, like __init__, __str__, __repr__, and so on. These methods allow you to customize the behavior of objects in various situations.

Purpose of Special Methods:

Special methods are used to define how objects of a class behave in specific situations. They help you make your objects more user-friendly and provide better control over how they are represented, compared, or interacted with.

Let's explore a few common special methods and their purposes:

__str__:

Purpose: It defines how an object should be represented as a string when you use the str() function or when you print the object.
Example:
  1. python
    class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"{self.name}, {self.age} years old" person = Person("Alice", 30) print(person) # Calls the __str__ method
    Output:
    sql
    Alice, 30 years old

__repr__:

Purpose: It defines how an object should be represented as a string when you use the repr() function or when you inspect the object in the Python shell.
Example:
python
class Person: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"Person('{self.name}', {self.age})" person = Person("Alice", 30) print(repr(person)) # Calls the __repr__ method
Output:
scss
Person('Alice', 30)

__add__:

Purpose: It defines how two objects of a class should be added together using the + operator.
Example:
python
class Point: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): # Define how to add two Point objects return Point(self.x + other.x, self.y + other.y) point1 = Point(1, 2) point2 = Point(3, 4) result = point1 + point2 # Calls the __add__ method print(result.x, result.y)
Output:
4 6
In these examples, we used special methods to customize how objects are represented as strings (__str__ and __repr__) and how they behave when added together (__add__). Special methods allow you to define your own logic for these operations, making your classes more intuitive and flexible.

Common Special Methods (Magic or Dunder Methods)

In Python, there are many special methods, often referred to as "magic" or "dunder" (short for "double underscore") methods. These methods are used to define custom behavior for objects. Here's a list of some common special methods:
  1. __init__: Constructor method, called when an object is created.
  2. __str__: Defines the string representation of an object (used by str() and print()).
  3. __repr__: Defines the unambiguous string representation of an object (used by repr() and interactive mode).
  4. __len__: Defines the length of an object (used by the len() function).
  5. __getitem__: Defines how to access elements using indexing (e.g., obj[3]).
  6. __setitem__: Defines how to set elements using indexing (e.g., obj[3] = value).
  7. __delitem__: Defines how to delete elements using indexing (e.g., del obj[3]).
  8. __iter__: Defines how to make an object iterable (used in loops).
  9. __next__: Defines how to get the next item when iterating.
  10. __contains__: Defines membership test operations (e.g., item in obj).
  11. __eq__: Defines the equality operation (e.g., obj1 == obj2).
  12. __ne__: Defines the inequality operation (e.g., obj1 != obj2).
  13. __lt__: Defines the less-than operation (e.g., obj1 < obj2).
  14. __le__: Defines the less-than-or-equal operation (e.g., obj1 <= obj2).
  15. __gt__: Defines the greater-than operation (e.g., obj1 > obj2).
  16. __ge__: Defines the greater-than-or-equal operation (e.g., obj1 >= obj2).
  17. __add__: Defines addition (e.g., obj1 + obj2).
  18. __sub__: Defines subtraction (e.g., obj1 - obj2).
  19. __mul__: Defines multiplication (e.g., obj1 * obj2).
  20. __truediv__: Defines division (e.g., obj1 / obj2).
  21. __floordiv__: Defines floor division (e.g., obj1 // obj2).
  22. __mod__: Defines modulo operation (e.g., obj1 % obj2).
  23. __pow__: Defines exponentiation (e.g., obj1 ** obj2).
  24. __and__: Defines bitwise AND (e.g., obj1 & obj2).
  25. __or__: Defines bitwise OR (e.g., obj1 | obj2).
  26. __xor__: Defines bitwise XOR (e.g., obj1 ^ obj2).
  27. __lshift__: Defines left shift (e.g., obj1 << obj2).
  28. __rshift__: Defines right shift (e.g., obj1 >> obj2).
  29. __neg__: Defines negation (e.g., -obj).
  30. __pos__: Defines unary plus (e.g., +obj).
  31. __abs__: Defines absolute value (e.g., abs(obj)).
  32. __round__: Defines rounding (e.g., round(obj)).
  33. __hash__: Defines a hash value for an object (used in dictionaries and sets).
  34. __call__: Allows an object to be called as a function (e.g., obj()).
This list covers many of the commonly used special methods in Python. Depending on your specific needs, you may implement some of these methods in your custom classes to customize their behavior.

Post a Comment

Previous Post Next Post