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.
Feature | Python | JavaScript (ES6+) |
---|---|---|
Class Definition | class MyClass: | class MyClass { ... } |
Constructor | __init__(self, ...) | constructor(...) |
Instance Reference | self (must be explicitly passed as the first argument to methods) | this (implicitly available, its value is determined by how the function is called) |
Instantiation | my_obj = MyClass() | const myObj = new MyClass() (the new keyword is required) |
Inheritance | class Child(Parent): | class Child extends Parent { ... } |
Calling Parent Methods | super().method() or super().__init__() | super.method() or super() |
Private Members | By convention: _ (protected), __ (pseudo-private, name mangling) | Language-level support: # (true private fields/methods) |
Inheritance Model | Supports multiple inheritance | Only supports single inheritance (multiple inheritance is simulated with the Mixin pattern) |
1. Class and Object Creation (Instantiation)
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
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 usesconstructor
. - Instance Reference: Python must explicitly pass
self
, whilethis
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.
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.
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.
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.
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.
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.
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 ofthis
and many other features of the JS object model.