Python vs JavaScript OOP 对比详解
1. Python 的 __xxx__ 方法(魔法方法/Dunder 方法)
Python 有大量的特殊方法,都是 双下划线开头和结尾。
常见的魔法方法
class MyClass:
# 对象生命周期
def __init__(self): # 初始化
pass
def __new__(cls): # 创建实例(比 __init__ 更早)
pass
def __del__(self): # 析构函数
pass
# 字符串表示
def __str__(self): # print(obj)
pass
def __repr__(self): # repr(obj),开发者表示
pass
# 比较运算符
def __eq__(self, other): # obj1 == obj2
pass
def __lt__(self, other): # obj1 < obj2
pass
def __le__(self, other): # obj1 <= obj2
pass
def __gt__(self, other): # obj1 > obj2
pass
def __ge__(self, other): # obj1 >= obj2
pass
def __ne__(self, other): # obj1 != obj2
pass
# 算术运算符
def __add__(self, other): # obj1 + obj2
pass
def __sub__(self, other): # obj1 - obj2
pass
def __mul__(self, other): # obj1 * obj2
pass
def __truediv__(self, other): # obj1 / obj2
pass
# 容器操作
def __len__(self): # len(obj)
pass
def __getitem__(self, key): # obj[key]
pass
def __setitem__(self, key, value): # obj[key] = value
pass
def __contains__(self, item): # item in obj
pass
def __iter__(self): # for x in obj
pass
# 属性访问
def __getattr__(self, name): # obj.attr(找不到时调用)
pass
def __setattr__(self, name, value): # obj.attr = value
pass
def __delattr__(self, name): # del obj.attr
pass
# 可调用
def __call__(self): # obj()
pass
# 上下文管理器
def __enter__(self): # with obj:
pass
def __exit__(self, *args): # with 结束时
pass
为什么有这么多?
因为 Python 希望你能自定义一切行为!
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __len__(self):
return int((self.x**2 + self.y**2)**0.5)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6) ← 调用 __add__
print(v1 * 3) # Vector(3, 6) ← 调用 __mul__
print(len(v1)) # 2 ← 调用 __len__
print(v1 == v2) # False ← 调用 __eq__
2. Python:类为主还是函数为主?
答案:Python 是多范式语言,既支持类也支持函数!
Python 支持多种编程范式
# 1. 面向对象(OOP)
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name}在叫")
# 2. 函数式编程
def double(x):
return x * 2
numbers = [1, 2, 3, 4]
result = list(map(double, numbers)) # [2, 4, 6, 8]
# 3. 过程式编程
x = 10
y = 20
z = x + y
print(z)
Python 的实际情况
# Python 标准库大量使用函数
import math
print(math.sqrt(16)) # 函数
import json
data = json.loads('{"a": 1}') # 函数
# 但也有很多类
from datetime import datetime
now = datetime.now() # 类
from pathlib import Path
p = Path("test.txt") # 类
# 甚至混用
import os
os.listdir(".") # 函数
path = os.path.join("a", "b") # 函数
# 但在类中
class MyClass:
pass
实际项目中的使用
# 数据科学:函数为主
import numpy as np
import pandas as pd
arr = np.array([1, 2, 3]) # 函数创建
df = pd.read_csv("data.csv") # 函数
result = df.mean() # 方法
# Web 框架:类和函数混用
from flask import Flask
app = Flask(__name__) # 类
@app.route('/') # 装饰器
def index(): # 函数
return "Hello"
# Django:类为主
from django.views import View
class MyView(View): # 类
def get(self, request):
return response
# PyTorch:类为主
import torch.nn as nn
class MyModel(nn.Module): # 类
def __init__(self):
super().__init__()
def forward(self, x):
return x
结论:Python 没有明显的"类为主"或"函数为主",看场景!
3. JavaScript vs Python:OOP 对比
JavaScript:函数是一等公民
// JS 中,类本质就是函数
class Dog {
constructor(name) {
this.name = name;
}
}
console.log(typeof Dog); // "function" ← 类就是函数!
// 等价的函数写法
function DogFunc(name) {
this.name = name;
}
// 都能用 new
const dog1 = new Dog("旺财");
const dog2 = new DogFunc("小黑");
Python:类是类,函数是函数
# Python 中,类和函数是不同的东西
class Dog:
def __init__(self, name):
self.name = name
def some_function():
pass
print(type(Dog)) # <class 'type'> ← 类是 type 的实例
print(type(some_function)) # <class 'function'> ← 函数是 function
# 不能这样用
# dog = Dog.call(None, "旺财") ❌ 不像 JS 的 apply/call
4. Python 是"真的"面向对象吗?
答案:Python 比 JavaScript 更加"纯粹"的面向对象!
Python:一切皆对象
# 数字是对象
x = 42
print(type(x)) # <class 'int'>
print(dir(x)) # [..., '__add__', '__mul__', ...]
print(x.__add__(8)) # 50(调用方法)
# 字符串是对象
s = "hello"
print(type(s)) # <class 'str'>
print(s.upper()) # HELLO
# 函数也是对象!
def my_func():
pass
print(type(my_func)) # <class 'function'>
my_func.custom_attr = "属性" # 可以给函数加属性!
print(my_func.custom_attr)
# 类也是对象!
class Dog:
pass
print(type(Dog)) # <class 'type'>
Dog.custom = "类属性"
print(Dog.custom)
# 模块也是对象!
import math
print(type(math)) # <class 'module'>