Day 09 · 面向对象思想与核心底层机制随堂精要
01 · 编程思想概述
思想是思考问题的方式,能直接决定具体的编码行为。编程思想则是指在编程过程中面对复杂需求时,分析与解决问题的方法论。
1. 面向过程 (POP - Procedure Oriented)
核心口诀:「凡事必躬亲」
- 更侧重于步骤与过程的把控;
- 典型代表语言:C 语言;
- 生活栗子:比如洗衣服,需要自己亲自「泡一泡 ➔ 搓一搓 ➔ 拧一拧 ➔ 晾一晾」。
2. 面向对象 (OOP - Object Oriented)
核心口诀:「自己的事情别人做,找对象解决问题」
- 更侧重于对象的使用与职能划分;
- 典型代表语言:Java、C++、Python;
- 生活栗子:洗衣服找「洗衣机」对象,把衣服放进去,按启动即可!
因为我们从出生到现在,一直在用面向对象的思维解决生活中的问题(饿了找外卖APP对象,去上学找学校对象)。《Thinking In Java》中有一句经典名言:「万物皆对象」。对象是能帮助你解决具体问题的事物,它不仅指现实实体,在代码世界里抽象的数据结构、模块和功能实体皆为对象。
02 · 类和对象的关系
在面向对象体系中,类与对象是不可分割的核心概念:
🏗️ 类 (Class)
一类事物的抽象与图纸:只要是一个名词,代表一种类别或类型(如 Student、Car、Person)。
📦 对象 (Instance)
此类事物的具体化产物:根据图纸制造出来的具体产品(如具体的学生「张三」、一辆具体的特斯拉)。
类是对象的模板,对象是根据类生产出来的具体实例。 我们日常写业务代码,真正干活、调用方法、操作属性的,正是具体的对象!
03 · 如何创建类和根据类创建对象
在 Python 中,通常使用事物描述类(Bean 类)来建模现实业务。类命名严格遵守大驼峰(PascalCase)规范:
class 类名:
"""类的说明文档,可通过 类名.__doc__ 访问"""
类属性 = 初始值 # 类变量,全类共享
def __init__(self, 形参1, 形参2):
self.形参1 = 形参1 # 实例属性
self.形参2 = 形参2
def 实例方法名(self):
pass
学生类 (Student) 完整实战案例
class Student:
"""描述学生这类事物的类"""
school = "atguigu"
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self, food):
print(f"姓名是 : {self.name} , 年龄是 : {self.age} 的学生在吃 {food}")
# 使用案例
stu1 = Student("张三", 18)
print(stu1.name) # 张三
stu1.eat("汉堡") # 语法糖调用
Student.eat(stu1, "肉夹馍") # 本质调用
04 · 深度分析 __init__ 与 __new__ 函数
__new__(cls):真正负责向内存申请空间、创建出实例对象的构造函数!必须返回创建出来的对象实例;
__init__(self):是对象的初始化函数。它接收 __new__ 返回的全新对象引用(即 self),负责对其属性进行一一赋值,不能有任何返回值。
05 · 类和对象使用的内存图解
理解 Python 面向对象的底层精髓,必须直观建立栈内存 (Stack)、堆内存 (Heap) 与方法区 (Method Area) 的映射关系:
- 方法区:加载类的字节码,存储类属性(如
school)与类中所有方法的代码块; - 堆内存 (Heap):由
__new__分配具体对象所占的独立空间,包含各个对象独有的__dict__实例属性及指向所属类的引用; - 栈内存 (Stack):存储函数调用栈帧及局部变量(如
stu1),变量本质上是指向堆内存对象物理地址的指针。
06 · self 的理解和用法
self 只能在类中使用。哪个具体的对象调用了这个带有 self 参数的方法,那这个方法内部的 self 指向的就是谁!
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print(f"{self.name} is studying hard!")
def show(self):
print(f"My name is {self.name}, and I am {self.age} years old.")
self.study() # 在实例方法内调用自身的其他实例方法,需要带上 self.
p1 = Person("Alice", 20)
p1.show()
07 · 属性的操作(类属性 vs 实例属性)
正确修改类属性:必须使用 类名.类属性 = 新值。
错误做法:若使用 对象名.类属性 = 新值,实际上是在该对象内部强行动态新建了一个同名的实例属性,产生遮蔽,底层类属性根本未变!
class Person:
school = "尚硅谷"
p1 = Person()
p2 = Person()
p1.school = "北京大学" # 仅给 p1 自身添加了同名实例属性
print(Person.school) # 输出: 尚硅谷 (未变)
print(p1.school) # 输出: 北京大学
print(p2.school) # 输出: 尚硅谷
# 正确方式:
Person.school = "五道口职业技术学院"
print(p2.school) # 输出: 五道口职业技术学院
08 · 方法的操作与分类
1. 实例方法 (Instance Method)
方法第一个形参必须是 self。既能读写实例属性,也可以访问类属性。
2. 类方法 (@classmethod)
使用 @classmethod 声明,首形参为 cls。只能读写类属性,无法访问任何实例属性。推荐直接通过 类名.类方法() 调用。
3. 静态方法 (@staticmethod)
使用 @staticmethod 声明,形参里既没有 self 也没有 cls。在逻辑上属于类的纯工具函数,完全依赖传入的实参。
4. 在类外定义函数并挂载
Python 允许将类外的普通函数赋值给类属性,挂载后带有 self 形式参数的函数可作为实例方法正常被调用。