python,oop【python】
文章目录
python oop
Python 中的 self 和 C++ 面向对象中的 this 指针核心作用相同——都用于指代“当前对象的实例”,但在语法和细节上有显著差异。可以理解为:self 是 Python 中“显式化的 this”,两者的设计目标一致,但使用方式不同。
python self 与 c++this 指针
-
指代当前实例
两者都在类的成员方法中使用,用于指向调用该方法的具体对象实例,从而访问实例的成员变量或成员方法。-
Python 中,通过
self.属性访问当前实例的属性:class Person: def __init__(self, name): self.name = name # self 指向当前 Person 实例 def say_hello(self): print(f"Hello, I'm {self.name}") # 通过 self 访问实例属性 -
C++ 中,通过
this->属性访问当前实例的属性(this可省略,编译器会自动补充):class Person { private: string name; public: Person(string name) { this->name = name; // this 指向当前 Person 实例 } void say_hello() { cout << "Hello, I'm " << this->name << endl; // 通过 this 访问实例属性 } };
-
-
区分成员与局部变量
当方法的参数名与实例属性名相同时,两者都用于区分“实例成员”和“局部变量”。-
Python 中必须显式用
self区分:class Person: def __init__(self, name): self.name = name # self.name 是实例属性,name 是局部参数 -
C++ 中用
this区分(若省略this,局部变量会覆盖成员变量):class Person { private: string name; public: Person(string name) { this->name = name; // this->name 是成员变量,name 是局部参数 } };
-
二、关键区别(语法与细节)
| 特性 | Python 中的 self | C++ 中的 this 指针 |
|---|---|---|
| 是否显式声明 | 必须显式作为方法的第一个参数声明(否则报错)。 | 隐式存在于非静态成员方法中,无需声明(由编译器自动传递)。 |
| 调用时是否传递 | 调用方法时无需手动传递(解释器自动将当前实例作为第一个参数传入)。 | 调用方法时无需手动传递(编译器自动将当前实例地址传入)。 |
| 能否重命名 | 可以(但不推荐),本质是一个普通参数名(例如写成 cls 或 self_obj)。 | 不能,this 是关键字,固定名称。 |
| 在静态方法中 | 静态方法(@staticmethod)中不能使用 self(因为静态方法不依赖实例)。 | 静态方法中不能使用 this(同理,静态方法属于类,不依赖实例)。 |
| 空值情况 | 实例方法中 self 一定指向有效实例(不会为 None)。 | 非静态成员方法中 this 一定指向有效实例(不会为 nullptr)。 |
| 指针/引用特性 | self 是实例的引用(Python 中无指针概念)。 | this 是指向实例的常量指针(Type* const this),不能被重新赋值。 |
三、典型示例对比
Python 中 self 的显式使用
class Car:
def __init__(self, color): # 必须显式声明 self 为第一个参数
self.color = color # 用 self 绑定实例属性
def drive(self): # 所有实例方法都必须带 self 参数
print(f"A {self.color} car is driving") # 通过 self 访问属性
# 创建实例并调用方法(无需传递 self)
my_car = Car("red")
my_car.drive() # 解释器自动将 my_car 作为 self 传入
C++ 中 this 的隐式使用
class Car {
private:
string color;
public:
Car(string color) { // 无需声明 this,编译器自动传入
this->color = color; // 用 this 区分成员与参数(可省略 this->)
}
void drive() { // 无需声明 this 参数
cout << "A " << color << " car is driving" << endl; // 隐式使用 this->color
}
};
// 创建实例并调用方法(无需传递 this)
Car my_car("red");
my_car.drive(); // 编译器自动将 &my_car 作为 this 传入
总结
- 核心一致:
self和this都是为了在成员方法中定位“当前对象实例”,实现对实例成员的访问和区分。 - 差异核心:Python 强制显式声明
self作为方法参数(更直观,符合“显式优于隐式”的设计哲学),而 C++ 中this是隐式的(由编译器处理,更简洁)。
理解这一点后,无论是从 Python 转向 C++ 还是反之,都能快速掌握面向对象中“当前实例”的访问逻辑。
Python 中的 __init__ 与 C++ 的构造函数作用相似但机制不同;Python 的析构函数是 __del__,但使用时需注意其局限性。以下是详细分析:
python init 与 C++ 构造函数的异同
1. 核心作用的相似性
两者的核心目标一致:在对象创建时初始化成员变量,为对象的使用做准备。
- 自动调用:对象实例化时自动执行(如
obj = MyClass(...))。 - 参数支持:允许接收参数,用于定制对象初始化逻辑。
2. 底层机制的关键差异
| 特性 | C++ 构造函数 | Python __init__ |
|---|---|---|
| 调用时机 | 对象创建时调用(内存分配后立即执行) | 对象创建后调用(内存由 __new__ 分配) |
| 内存管理 | 负责分配内存 + 初始化(如栈/堆上的对象创建) | 仅负责初始化,内存分配由 __new__ 完成 |
| 继承行为 | 自动调用父类构造函数 | 需手动调用 super().__init__() 触发父类初始化 |
| 返回值 | 无返回值 | 必须返回 None(Python 强制) |
| 重载支持 | 支持(多个构造函数参数不同) | 仅支持“默认参数”模拟重载(如 def __init__(self, a=1, b=2): ...) |
3. 代码示例对比
C++ 构造函数(负责内存分配 + 初始化):
class Person {
public:
string name;
int age;
// 构造函数:在对象创建时分配内存并初始化
Person(string n, int a) : name(n), age(a) {
cout << "C++ 构造函数调用:" << name << " " << age << endl;
}
};
int main() {
Person p("cxq", 22); // 构造函数自动调用
return 0;
}
Python __init__(仅初始化,内存由 __new__ 分配):
class Person:
def __new__(cls, *args, **kwargs):
print("__new__ 分配内存")
return super().__new__(cls) # 实际分配内存的是 __new__
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Python __init__ 初始化:{name} {age}")
p = Person("cxq", 22) # 先调用 __new__ 分配内存,再调用 __init__ 初始化
Python 的析构函数_del_与c++析构函数
Python 的析构函数是 __del__,用于在对象被垃圾回收时执行清理操作(如释放文件句柄、关闭网络连接等)。但它的行为与 C++ 析构函数(如 ~Person())有本质区别。
1. __del__ 的基本行为
- 自动调用时机:当对象的引用计数降为 0 时,解释器自动调用
__del__。 - 资源清理:适合释放简单资源(如临时文件),但不推荐用于关键资源(如数据库连接)。
2. 与 C++ 析构函数的关键差异
| 特性 | C++ 析构函数 | Python __del__ |
|---|---|---|
| 调用时机 | 确定性调用(对象离开作用域或 delete 时) | 不确定性(依赖垃圾回收,循环引用时可能延迟或不调用) |
| 资源管理 | 可靠释放资源(如堆内存、文件句柄) | 不推荐用于关键资源(调用时机不确定) |
| 异常处理 | 析构函数中抛出异常会导致程序崩溃 | __del__ 中异常会被静默忽略(Python 解释器自动吞掉异常) |
3. 代码示例与注意事项
Python __del__ 示例:
class Resource:
def __init__(self, name):
self.name = name
print(f"资源 {name} 已创建")
def __del__(self):
print(f"资源 {self.name} 已销毁")
# 场景1:无循环引用,引用计数归零时调用 __del__
obj = Resource("文件1")
del obj # 引用计数降为0,触发 __del__ → 输出“资源 文件1 已销毁”
# 场景2:循环引用,__del__ 可能延迟调用
class Node:
def __init__(self, name):
self.name = name
self.next = None
def __del__(self):
print(f"Node {self.name} 已销毁")
a = Node("A")
b = Node("B")
a.next = b
b.next = a # 循环引用
del a, b # 引用计数不为0,需等待垃圾回收器介入
import gc
gc.collect() # 手动触发垃圾回收,此时才会调用 __del__
4. __del__ 的局限性与替代方案
-
局限性:
- 循环引用时,
__del__可能延迟调用甚至不调用(需依赖垃圾回收器)。 - 程序异常退出时,
__del__可能不会执行(如os._exit()或信号终止)。 - 异常在
__del__中被静默忽略,难以调试。
- 循环引用时,
-
推荐替代方案:
- 上下文管理器(
with语句 +__enter__/__exit__):可靠管理资源(如文件、锁)。 - 显式清理方法:定义
close()等方法,手动调用释放资源。
- 上下文管理器(
三、总结
__init__与 C++ 构造函数:作用相似(初始化对象),但机制不同(Python 中内存分配由__new__负责,C++ 构造函数同时处理分配与初始化)。- Python 析构函数:是
__del__,但调用时机不确定,不适合关键资源管理,建议用上下文管理器或显式清理方法替代。
理解这些差异有助于避免跨语言开发时的陷阱,尤其是资源管理和对象生命周期方面的问题。
更多推荐


所有评论(0)