An object, in normal language, refers to physical items that you can see, touch, or feel. Objects usually have properties associated with them.  Such  properties can include nameageshape, size, color, etc. They can also perform actions for example, a dog can bark, walk, eat, play, among other things.

Well in software engineering, Objects are not necessarily things that we can, pick up,  see, touch, or feel. However,  they are models of real life objects  that can do such things. The best example of a software object is a character in a modern video game.

Objects are entities in a program that are made up of data(properties) and behaviors (actions). They enable developers to model real-world objects and scenarios. For example, an object representing a character in a video game can contain properties such as name, health, maximum speed, etc.  and actions such as attack, fire, run, etc

If you are not absolutely new to Python (or any other object-oriented language), you have already, in one way or another, interacted with objects. 

Object-oriented programming (OOP) is a type of programming that is centered around the concept of objects. 

Objects and Classes

So an object is a collection of data  and associated behaviors. But how do we differentiate between different objects?. While  a human and a car are both objects, the data and behaviors associated with them are entirely different.  Classes are the blueprints from which individual objects are created. Thus two cars will belong to the same class but a human and a car will belong to different classes.

A class defines the data and behaviors that an object of that class should contain. Thus, when creating different kinds of objects, we can use classes to establish a common set of data and behaviors. This allows us to differentiate between different objects while also ensuring that they share similar set of data and behaviors.  So while two humans might have different names, or two cars might be of different colors, they both share a common set of data  i.e they both have a name and color associated with each of them(respectively).

A class is an abstract thing, it provides a structure or template that defines the properties and methods that an object of the class will possess. It also provides the basis for creating objects of that class, which are unique and have their own values.

Attributes and Methods

Objects contains data(properties) and behaviors(actions).

Data/Properties Describe objects

Properties are typically used to store information about an individual object, such as its size, shape, color, or properties of any other type. Objects belonging to the same class will have same set of properties. For example all cars have make, model, year, color, engine, etc. Obviously, different cars may have different values for a particular property.

Another common use of properties is to define relationships between objects. In an object-oriented design, when two classes are related, properties can be used to link them. This allows for an object to contain references to other objects, which can be used to model complex relationships between objects.  For example a human can own a car, In which case a human object will have a property referencing an instance of a car class.

Defining properties is done just like how we set normal variables but within a class.

Other names used to refer to properties include members and attributes.

Behavior are Actions

Behaviors in object related programming refers to actions that determines how object interacts with the rest of the program. These behaviors are called methods of that object. They are  invoked when a particular event happens or when a direct call is made to the method. They are typically implemented as special functions, performing an action is simply calling the relevant method/function.

For example a fighter in a modern video game can have a method called  attack() which when invoked,  may cause the fighter to move toward the enemy and launch a series of physical attacks or attacks using weapons.

The name "method" is mostly reserved for functions that are associated with an object/class while the name 'function'  is used for the normal/traditional functions i.e those that are not associated with an object or a class.

Abstraction in Object Oriented Programming

Abstraction is the process of representing the essential details of an object while hiding away the non-essential details. For example  in case of a car object, some of the things that might be relevant to the user or other objects interacting with the car object  maybe things such as the Make , the model , cost, etc. While it may not be relevant to tell the end user the number of cylinders in the engine, the number of valves in the engine, etc. 

Remember that an object is used by other objects in the program as well as the end users. For example the characters and other objects written by a game developer  will be interacted with by the end user when playing the game. Abstraction, therefore, helps in hiding unnecessary details about each object from the user.

Abstraction allows the distinction between the public interface and  private implementation details of an object. Each object have its own implementation details that are hidden from the outside. This makes it easier to change or extend the implementations without affecting the other objects as long as the public interface remains the same.

Abstraction aims at showing the end user the most relevant details to them. By presenting only what is relevant to the user, it eliminates any confusion caused by unnecessary complexity.

Composition

Composition is  a technique used when an object is made up of other objects and its functionality relies on the other objects. With composition, an object can be composed of one or more other objects also called components. The composed object has the combined behavior of all its components.

For example a car is composed of an engine, wheels, etc. The behavior of the car is determined by the behavior of each individual component. Thus if we are defining a car object, we can define the various components differently then combine them to form end object. for example we might have a separate Engine class, Wheel class, etc.

Composition  in OOP is a powerful technique because  it allows us to create objects that interact with each other in an organized structure. This aids in creating complex software programs that are more extensible, maintainable, and performant.

Inheritance

Inheritance is a fundamental concept of OOP and it is one of the main characteristics that distinguishes OOP from other programming paradigms. It is also the over-used relationship in object-oriented programming. 

Inheritance allows classes to reuse, extend, and modify the behavior of existing classes. This increases code clarity by allowing developers to create hierarchical structures and a better organization of object classes. For example in a case where we have a car and a truck.  It would be trivial and redundant  to define both of this classes from scratch. This is because a car and a truck have far more in common than they have  different.  With inheritance, you can define a class for the more general concept of a Vehicle, and then define separate classes for cars and trucks which 'inherit' their characteristics from the parent class i.e Vehicle. This allows you to define each type of vehicle by only specifying the features that are unique to it and which separates each from other type of vehicles..

Inheritance aids in creating classes that share common characteristics and behaviors. This allows us to write code that is easier to maintain and reuse, as well as allowing us to easily add features and modify existing ones without having to rewrite the whole class from scratch.

The class that unites the several classes is called the "base class" or the "parent class". Any class that inherits from a base class is called a derived class.  For example the Vehicle class is the base class while Car and Truck are derived classes.

It is also common to use multiple inheritance in which case one class inherits characteristics and features from more than one base classes. This helps in modeling real-world relationships and problems more accurately and efficiently. Making it easier to develop a more finely grained, complex system that better reflects the real world.