本文总结了Python面向对象编程的核心概念,并与JavaScript进行了对比。
主要内容包括:
- Python类与对象的定义、属性方法、封装继承多态三大特性、特殊方法等基础知识;
- 通过对比表展示两种语言在语法、继承、封装、方法绑定等方面的差异;
- 最后分析各自优缺点及适用场景。
Python采用基于类的继承模型,语法简洁明确;
JavaScript基于原型继承,灵活性更高但学习曲线较陡。
建议初学者从Python入手理解OOP基础,前端开发者则需掌握JavaScript的OOP实现。
Python 面向对象总结:对比 JavaScript 的面向对象
Python面向对象编程总结(初学者版)
一、基本概念
1. 类与对象
-
类:对象的蓝图或模板
-
对象:类的实例,具体存在的实体
python
# 定义类
class Student:
pass
# 创建对象
stu1 = Student()
stu2 = Student()
二、类的核心组成
1. 属性(变量)
python
class Dog:
# 类属性(所有实例共享)
species = "Canis familiaris"
def __init__(self, name, age):
# 实例属性(每个实例独立)
self.name = name
self.age = age
# 使用
dog1 = Dog("旺财", 3)
print(dog1.name) # 旺财
print(Dog.species) # Canis familiaris
2. 方法(函数)
python
class Cat:
def __init__(self, name):
self.name = name
# 实例方法(最常用)
def meow(self):
print(f"{self.name}喵喵叫")
# 类方法
@classmethod
def create_default(cls):
return cls("默认猫")
# 静态方法
@staticmethod
def sound():
print("喵~")
# 调用
cat = Cat("咪咪")
cat.meow() # 咪咪喵喵叫
三、构造方法与初始化
__init__ 方法
python
class Person:
def __init__(self, name, age):
self.name = name # 初始化属性
self.age = age
print(f"创建了{name}")
# 创建对象时自动调用__init__
p = Person("张三", 20) # 输出:创建了张三
四、封装(访问控制)
python
class BankAccount:
def __init__(self, balance):
self.balance = balance # 公开属性
self._password = "123456" # 单下划线:约定私有
self.__secret = "secret" # 双下划线:名称修饰
# 公开方法
def get_balance(self):
return self.balance
# 属性装饰器(更好的封装)
@property
def password(self):
return "***"
@password.setter
def password(self, value):
if len(value) >= 6:
self._password = value
# 使用
account = BankAccount(1000)
print(account.balance) # 可以访问
print(account._password) # 可以但不推荐
# print(account.__secret) # 错误:无法直接访问
print(account.password) # 通过属性访问
五、继承
1. 单继承
python
# 父类
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name}在吃东西")
# 子类
class Dog(Animal):
def bark(self):
print(f"{self.name}在汪汪叫")
# 重写父类方法
def eat(self):
print(f"{self.name}在吃狗粮")
# 使用
dog = Dog("旺财")
dog.eat() # 旺财在吃狗粮(调用子类方法)
dog.bark() # 旺财在汪汪叫
2. 多继承
python
class Flyable:
def fly(self):
print("飞行中")
class Swimmable:
def swim(self):
print("游泳中")
class Duck(Flyable, Swimmable):
pass
duck = Duck()
duck.fly() # 飞行中
duck.swim() # 游泳中
3. super() 调用父类
python
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # 调用父类__init__
self.age = age
六、多态
python
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
# 多态:同一个方法在不同类中有不同实现
shapes = [Circle(5), Rectangle(4, 6)]
for shape in shapes:
print(shape.area()) # 自动调用对应的方法
七、特殊方法(魔术方法)
python
class Book:
def __init__(self, title, pages):
self.title = title
self.pages = pages
# 字符串表示
def __str__(self):
return f"《{self.title}》"
def __repr__(self):
return f"Book('{self.title}', {self.pages})"
# 比较运算
def __eq__(self, other):
return self.pages == other.pages
def __lt__(self, other):
return self.pages < other.pages
# 长度
def __len__(self):
return self.pages
book1 = Book("Python入门", 300)
book2 = Book("高级编程", 500)
print(str(book1)) # 《Python入门》
print(len(book1)) # 300
print(book1 < book2) # True
八、常用特殊方法速查表
| 方法 | 触发时机 | 作用 |
|---|---|---|
__init__ |
创建对象时 | 初始化 |
__str__ |
print(对象) | 用户友好显示 |
__repr__ |
交互式环境 | 开发者友好显示 |
__len__ |
len(对象) | 返回长度 |
__getitem__ |
对象[key] | 索引访问 |
__setitem__ |
对象[key]=值 | 索引赋值 |
__call__ |
对象() | 使对象可调用 |
九、最佳实践建议
-
类名使用驼峰命名法 :
MyClass -
方法名使用小写+下划线 :
my_method -
私有属性用单下划线开头 :
_internal -
不要过度使用继承,优先使用组合
-
每个类应该有明确的单一职责
十、完整示例
python
class BankAccount:
"""银行账户类"""
bank_name = "Python银行" # 类属性
account_count = 0 # 账户计数器
def __init__(self, owner, initial_balance=0):
self.owner = owner
self._balance = initial_balance
self._transactions = []
BankAccount.account_count += 1
def deposit(self, amount):
"""存款"""
if amount > 0:
self._balance += amount
self._transactions.append(f"+{amount}")
return True
return False
def withdraw(self, amount):
"""取款"""
if 0 < amount <= self._balance:
self._balance -= amount
self._transactions.append(f"-{amount}")
return True
return False
@property
def balance(self):
"""只读属性"""
return self._balance
def __str__(self):
return f"账户[{self.owner}]: {self._balance}元"
@classmethod
def total_accounts(cls):
"""类方法:统计账户总数"""
return cls.account_count
# 使用示例
acc1 = BankAccount("张三", 1000)
acc2 = BankAccount("李四", 500)
acc1.deposit(200)
acc1.withdraw(150)
print(acc1) # 账户[张三]: 1050元
print(f"总账户数: {BankAccount.total_accounts()}") # 总账户数: 2
Python与JavaScript面向对象对比表
一、基础语法对比
| 特性 | Python | JavaScript | 说明 |
|---|---|---|---|
| 类定义 | class MyClass: |
class MyClass {} |
JS使用花括号,Python使用冒号+缩进 |
| 构造函数 | def __init__(self): |
constructor() {} |
名称不同,功能相似 |
| 属性访问 | self.name |
this.name |
关键字不同 |
| 实例创建 | obj = MyClass() |
const obj = new MyClass() |
JS必须用new(ES6类) |
| 方法定义 | def method(self): |
method() {} |
Python必须显式写self参数 |
| 私有属性 | self.__name(名称修饰) |
#name(提案阶段)或闭包 |
Python更常用单下划线_name约定 |
二、继承对比
| 特性 | Python | JavaScript | 说明 |
|---|---|---|---|
| 单继承 | class Child(Parent): |
class Child extends Parent |
语法类似 |
| 多继承 | ✅ 支持 class C(A,B): |
❌ 不支持(可用Mixin替代) | Python独有特性 |
| 调用父类 | super().__init__() |
super() 或 super.method() |
都需要在子类构造函数中调用 |
| 方法重写 | 直接定义同名方法 | 直接定义同名方法 | 两者都支持 |
| 父类方法调用 | super().method() |
super.method() |
语法差异 |
三、封装与访问控制
| 特性 | Python | JavaScript | 说明 |
|---|---|---|---|
| 公开属性 | self.name |
this.name |
默认都是公开 |
| 约定私有 | self._name(单下划线) |
_name(约定俗成) |
都是约定,非强制 |
| 真正私有 | self.__name(名称修饰) |
#name(需启用) |
Python的会被改名但可访问 |
| 属性访问器 | @property装饰器 |
get/set关键字 |
功能相似 |
| 只读属性 | @property不定义setter |
get方法不定义set |
Python语法更简洁 |
python
# Python属性装饰器
class Person:
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
javascript
// JavaScript属性访问器
class Person {
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
}
四、方法与函数
| 特性 | Python | JavaScript | 说明 |
|---|---|---|---|
| 实例方法 | 需要self参数 |
不需要特殊参数 | Python显式,JS隐式 |
| 类方法 | @classmethod + cls |
static关键字 |
名称和语法不同 |
| 静态方法 | @staticmethod |
static关键字 |
功能相同 |
| this/self绑定 | 自动绑定 | 需要关注绑定问题 | JS的this容易出错 |
| 箭头函数 | ❌ 不支持 | ✅ () => {} |
可解决this绑定 |
javascript
// JS的this绑定问题
class Counter {
constructor() {
this.count = 0;
// 需要绑定this
setInterval(this.increment.bind(this), 1000);
}
increment() {
this.count++;
}
}
五、特殊方法对比
| Python | JavaScript | 说明 |
|---|---|---|
__init__ |
constructor |
构造函数 |
__str__ |
toString() |
字符串表示 |
__repr__ |
[Symbol.toPrimitive] |
开发者表示 |
__len__ |
length属性 |
长度 |
__add__ |
valueOf() |
加法运算 |
__call__ |
函数对象 | 使对象可调用 |
__getitem__ |
Proxy |
索引访问 |
六、原型链vs类继承
| 特性 | Python | JavaScript | 说明 |
|---|---|---|---|
| 继承模型 | 基于类的继承 | 基于原型的继承 | JS本质是原型继承 |
| 类本质 | 真正的类 | 语法糖(本质是函数) | Python类是对象 |
| 动态性 | 较低(可修改但有限) | 极高(可动态修改原型) | JS更灵活 |
| 性能 | 较高 | 原型链查找有开销 | Python类更快 |
| 元类 | ✅ 支持(高级特性) | ❌ 无(Proxy可模拟) | Python独有 |
七、代码示例对比
Python:
python
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
dog = Dog("旺财")
print(dog.speak()) # 旺财 says Woof!
JavaScript:
javascript
class Animal {
constructor(name) {
this.name = name;
}
speak() {
// 空方法
}
}
class Dog extends Animal {
speak() {
return `${this.name} says Woof!`;
}
}
const dog = new Dog("旺财");
console.log(dog.speak()); // 旺财 says Woof!
八、优缺点对比
| 维度 | Python | JavaScript |
|---|---|---|
| 学习曲线 | 平缓,语法简洁 | 中等,this绑定和原型较复杂 |
| 代码可读性 | 极高(强制缩进) | 一般(花括号风格多样) |
| 灵活性 | 较低 | 极高(可随时修改对象) |
| 错误检查 | 运行时检查 | 运行时检查 |
| 类型系统 | 动态强类型 | 动态弱类型 |
| 多继承 | ✅ 支持 | ❌ 不支持(但可用Mixin) |
| 私有属性 | 有(名称修饰) | 较新(#字段) |
| 装饰器 | ✅ 原生支持 | ❌ 需Babel或高阶函数 |
九、最佳使用场景
| 场景 | 推荐语言 | 原因 |
|---|---|---|
| 后端开发 | Python | 成熟框架(Django/Flask) |
| 前端开发 | JavaScript | 浏览器原生语言 |
| 数据分析 | Python | Pandas/Numpy生态 |
| 移动开发 | JavaScript | React Native/Flutter |
| 科学计算 | Python | 丰富科学计算库 |
| 全栈开发 | JavaScript | Node.js统一前后端 |
| 快速原型 | Python | 简洁语法开发快 |
| 大型应用 | TypeScript(JS超集) | 类型安全 |
十、核心要点总结
| 核心差异 | Python | JavaScript |
|---|---|---|
| 继承机制 | 类继承 | 原型继承(类只是语法糖) |
| this/self | 显式self参数 | 隐式this,需注意绑定 |
| 多继承 | 原生支持 | 不支持 |
| 私有属性 | __name(名称修饰) |
#name(较新特性) |
| 动态性 | 有限 | 非常灵活 |
| 学习难度 | 简单 | 中等(原型链难理解) |
选择建议:
-
新手学Python更容易理解OOP基础
-
需要Web前端必须学JavaScript OOP
-
两者都精通能更好理解不同OOP范式