Skip to content

Python vs. JavaScript: A Guide to Object-Oriented Programming (OOP)

Object-Oriented Programming (OOP) is a core programming paradigm that uses "objects" to design software. This document aims to provide an in-depth comparison of the core philosophies, syntax structures, and implementation differences in object-oriented programming between Python and JavaScript.


Core Philosophies and Concepts

  • Python: A Classic, Explicit Class Model Python was designed from the ground up as a clear, traditional class-based object-oriented language. Its OOP model is direct and explicit, following its core philosophy of "explicit is better than implicit."

  • JavaScript: Evolution from Prototypes to Classes JavaScript's foundation is a prototype-based inheritance model, which is a more flexible but also more unusual way of handling inheritance. The class keyword introduced in ES6 is primarily "syntactic sugar" over this prototype-based inheritance. It makes the code look more like traditional OOP, but its underlying mechanism is completely different from languages like Python.

FeaturePythonJavaScript (ES6+)
Class Definitionclass MyClass:class MyClass { ... }
Constructor__init__(self, ...)constructor(...)
Instance Referenceself (must be explicitly passed as the first argument to methods)this (implicitly available, its value is determined by how the function is called)
Instantiationmy_obj = MyClass()const myObj = new MyClass() (the new keyword is required)
Inheritanceclass Child(Parent):class Child extends Parent { ... }
Calling Parent Methodssuper().method() or super().__init__()super.method() or super()
Private MembersBy convention: _ (protected), __ (pseudo-private, name mangling)Language-level support: # (true private fields/methods)
Inheritance ModelSupports multiple inheritanceOnly supports single inheritance (multiple inheritance is simulated with the Mixin pattern)

1. Class and Object Creation (Instantiation)

Python

python
class Dog:
    # Constructor
    def __init__(self, name, breed):
        self.name = name  # Instance attribute
        self.breed = breed

    # Instance method, self is required
    def bark(self):
        return f"{self.name} says woof!"

# Instantiation
my_dog = Dog("Rex", "German Shepherd")
print(my_dog.bark()) # -> "Rex says woof!"

JavaScript

javascript
class Dog {
  // Constructor
  constructor(name, breed) {
    this.name = name; // Instance attribute
    this.breed = breed;
  }

  // Instance method, this is implicit
  bark() {
    return `${this.name} says woof!`;
  }
}

// Instantiation, 'new' is required
const myDog = new Dog("Rex", "German Shepherd");
console.log(myDog.bark()); // -> "Rex says woof!"

Core Comparison:

  • Constructor: Python uses __init__, JS uses constructor.
  • Instance Reference: Python must explicitly pass self, while this in JS is implicitly available.
  • Instantiation: JS requires the new keyword, while Python does not.

2. Properties and Methods

Python

Python clearly distinguishes between instance attributes and class attributes.

python
class Car:
    # Class attribute, shared by all instances
    wheels = 4

    def __init__(self, color):
        # Instance attribute
        self.color = color

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

print(car1.wheels) # -> 4
print(Car.wheels)  # -> 4

JavaScript

Traditionally, all properties were defined in the constructor, but modern JS also supports public class fields, making it more similar to Python.

javascript
class Car {
  // Public class field, shared by all instances (similar to Python's class attribute)
  wheels = 4;

  constructor(color) {
    // Instance attribute
    this.color = color;
  }
}

const car1 = new Car("red");
const car2 = new Car("blue");

console.log(car1.wheels); // -> 4
// console.log(Car.wheels); // Static public fields are supported since ES2022

3. Inheritance

Python

Supports multiple inheritance with a concise syntax.

python
class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        raise NotImplementedError

class Dog(Animal): # Inherits from Animal
    def speak(self):
        return "Woof!"

# Multiple Inheritance
class Flyer:
    def fly(self):
        return "I can fly!"

class FlyingDog(Dog, Flyer): # Inherits from both Dog and Flyer
    pass

my_flying_dog = FlyingDog("Sparky")
print(my_flying_dog.speak()) # -> "Woof!"
print(my_flying_dog.fly())   # -> "I can fly!"

JavaScript

Only supports single inheritance, using the extends and super keywords.

javascript
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    throw new Error("speak() must be implemented by subclasses");
  }
}

class Dog extends Animal { // Inherits from Animal
  // If the subclass has a constructor, super() must be called first
  constructor(name, breed) {
    super(name); // Calls the parent class's constructor
    this.breed = breed;
  }
  speak() {
    return "Woof!";
  }
}

const myDog = new Dog("Buddy", "Golden Retriever");
console.log(myDog.speak()); // -> "Woof!"

4. Encapsulation and Privacy

This is a very critical difference between the two.

Python: Privacy by Convention

Python does not have true privacy and instead relies on naming conventions.

  • _protected (single underscore): Signals to other developers that this is an internal attribute and is "protected," but should not be accessed from outside. This is just a gentleman's agreement.
  • __private (double underscore): Triggers Name Mangling. The Python interpreter renames it to _ClassName__private, making it harder to access from the outside, but it is still not truly private.
python
class MyClass:
    def __init__(self):
        self._protected_var = 1
        self.__private_var = 2
    
    def get_private(self):
        return self.__private_var

obj = MyClass()
print(obj._protected_var) # -> 1 (accessible, but not recommended)
# print(obj.__private_var)  # -> AttributeError
print(obj._MyClass__private_var) # -> 2 (still accessible)

JavaScript: True Privacy

Modern JavaScript uses the # prefix to create truly private fields and methods that are completely inaccessible from outside the class.

javascript
class MyClass {
  #privateVar = 2; // Private field

  constructor() {
    this.publicVar = 1;
  }

  getPrivate() {
    return this.#privateVar; // Accessible internally
  }
}

const obj = new MyClass();
console.log(obj.publicVar); // -> 1
console.log(obj.getPrivate()); // -> 2
// console.log(obj.#privateVar); // -> SyntaxError

5. Underlying Model: Class vs. Prototype

  • Python is a pure class-based language. A class is a blueprint for creating objects, and an object is an instance of a class.
  • JavaScript's class syntax is syntactic sugar built on top of its prototype-based inheritance model. Every object has an internal link to another object called its "prototype," from which it inherits properties and methods. Understanding this helps explain the dynamic behavior of this and many other features of the JS object model.