Python是一门纯面向对象语言,一切皆对象。面向对象编程(OOP)是中高级Python开发、框架源码、项目架构设计的核心思想,主打封装、继承、多态三大特性。
本文全覆盖指定重难点知识点:类与实例、继承与多态、property属性装饰器、类方法/静态方法、__slots__内存优化、高频魔法方法。全程搭配可落地实战代码、底层原理拆解、工程高频坑点、大厂面试真题,一站式吃透Python OOP核心。
一、面向对象基础:类与实例
面向对象两个核心概念:**类(Class)**是模板、抽象定义;**实例(Instance)**是根据模板创建的具体对象,拥有类的属性和方法。
类统一描述属性(数据)和方法(行为),实例独享各自属性数据、共享类方法。
1.1 类与实例基础定义
# 定义类:模板
class Person:
# 类属性:所有实例共享
species = "人类"
# 初始化方法:实例属性初始化
def __init__(self, name, age):
# 实例属性:每个实例独有
self.name = name
self.age = age
# 实例方法
def introduce(self):
print(f"我是{self.name},今年{self.age}岁")
# 创建实例(实例化)
p1 = Person("张三", 18)
p2 = Person("李四", 20)
# 调用实例方法、访问属性
p1.introduce()
print(p1.name, p1.age)
print(Person.species)
1.2 类属性 vs 实例属性(高频坑点)
1、类属性:定义在类内部、方法外部,所有实例共享,内存仅存一份,适合公共常量、配置;
2、实例属性:定义在__init__中,绑定self,每个实例独立私有,互不干扰;
3、核心坑点:实例赋值类属性,会动态创建同名实例属性,屏蔽原类属性,不会修改类属性。
class Person:
species = "人类"
p1 = Person()
p2 = Person()
# 实例修改,只会新增实例属性,不改动类属性
p1.species = "超人"
print(p1.species) # 超人(实例属性)
print(p2.species) # 人类(类属性)
print(Person.species) # 人类
二、继承与多态(OOP三大特性核心)
面向对象三大特性:封装、继承、多态。继承实现代码复用,多态实现接口统一、差异化逻辑,是框架设计的核心思想。
2.1 继承机制
子类继承父类,自动拥有父类所有属性和方法,支持单继承、多继承,可重写父类方法实现功能拓展。
# 父类
class Animal:
def eat(self):
print("动物需要进食")
# 子类继承父类
class Dog(Animal):
# 子类重写父类方法
def eat(self):
print("狗狗吃狗粮")
# 子类独有方法
def bark(self):
print("汪汪叫")
dog = Dog()
dog.eat() # 执行重写后的方法
dog.bark()
2.2 多继承与MRO顺序
Python支持多继承,子类可同时继承多个父类,方法查找遵循MRO算法(广度优先),解决方法冲突问题。
class A:
def show(self):
print("A")
class B:
def show(self):
print("B")
# 多继承
class C(A, B):
pass
c = C()
c.show() # 优先继承靠前父类A
print(C.__mro__) # 查看方法查找顺序
2.3 多态特性
多态:父类引用指向子类对象,同一方法调用,不同子类实现不同逻辑,统一调用入口,适配不同业务实现。
class Animal:
def speak(self):
pass
class Cat(Animal):
def speak(self):
print("喵喵")
class Dog(Animal):
def speak(self):
print("汪汪")
# 多态统一调用
def animal_speak(animal: Animal):
animal.speak()
animal_speak(Cat())
animal_speak(Dog())
三、属性装饰器 @property
@property 是Python内置属性装饰器,将方法伪装成属性调用,无需括号,实现属性的读取、修改、删除权限管控,兼顾数据封装与简洁调用。
3.1 基础只读属性
class Student:
def __init__(self, name, score):
self.name = name
self.__score = score # 私有属性
# 伪装为属性,只读
@property
def level(self):
if self.__score >= 90:
return "优秀"
elif self.__score >= 60:
return "及格"
else:
return "不及格"
stu = Student("张三", 88)
print(stu.level) # 像属性一样调用,无需括号
# stu.level = "优秀" # 报错:只读属性无法赋值
3.2 读写属性(setter)
class Student:
def __init__(self, score):
self.__score = score
@property
def score(self):
return self.__score
# 属性赋值拦截,可做数据校验
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError("分数必须为整数")
if 0 <= value <= 100:
self.__score = value
else:
raise ValueError("分数范围0-100")
stu = Student(80)
stu.score = 95
print(stu.score)
# stu.score = 101 # 主动拦截报错
3.3 核心作用
1、简化调用:方法变属性,代码更优雅;
2、数据校验:拦截属性赋值,过滤非法数据;
3、权限控制:实现只读、读写、删除权限管控;
4、兼容旧代码:属性改方法无需修改业务调用。
四、实例方法 / 类方法 / 静态方法
Python类中三种方法,参数、调用方式、使用场景完全不同,是工程开发高频区分考点。
4.1 三种方法核心区别总览
1、实例方法:默认参数self,绑定实例,只能实例调用,操作实例属性;
2、类方法:装饰器@classmethod,默认参数cls,绑定类,类/实例均可调用,操作类属性;
3、静态方法:装饰器@staticmethod,无默认参数,不绑定类和实例,纯工具方法。
4.2 代码实战演示
class Person:
count = 0 # 类属性
def __init__(self, name):
self.name = name
Person.count += 1
# 1. 实例方法
def self_info(self):
print(f"实例名称:{self.name}")
# 2. 类方法
@classmethod
def get_count(cls):
print(f"总人数:{cls.count}")
# 3. 静态方法
@staticmethod
def help_msg():
print("这是Person类工具方法")
# 调用
p = Person("张三")
p.self_info()
Person.get_count() # 类调用
p.get_count() # 实例也可调用
Person.help_msg()
4.3 场景选型规范
1、需要操作实例属性 → 实例方法;
2、需要操作类属性、通用类逻辑 → 类方法;
3、无需依赖类和实例,纯独立工具逻辑 → 静态方法。
五、__slots__ 内存优化(工程优化重点)
默认情况下,Python实例通过**__dict__字典存储属性,字典内存占用大、效率低。__slots__**可以固定实例属性,禁用__dict__,大幅降低海量实例内存占用。
5.1 基础用法与优化效果
class Student:
# 固定当前类实例仅允许的属性
__slots__ = ["name", "age"]
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student("张三", 18)
print(stu.name, stu.age)
# 报错!不允许新增未声明属性
# stu.score = 100
5.2 核心特性与坑点
优势:海量实例场景(百万级对象)内存占用降低50%以上,访问速度更快;
限制:禁止实例动态新增属性,仅允许使用slots声明的属性;
继承坑点:子类默认继承父类slots,同时可扩展自身slots属性。
适用场景:批量创建大量相似小对象(爬虫实体、数据模型、ORM映射对象)。
六、高频魔法方法详解(__init__ / __call__ / __getitem__)
魔法方法是以**双下划线__**包裹的内置方法,无需手动调用,特定场景自动触发,是Python语法优雅的底层支撑。本文重点讲解工程&面试最高频的三个魔法方法。
6.1 __init__ 初始化方法
实例化对象时自动触发,用于初始化实例属性,是最常用的魔法方法。
class Person:
def __init__(self, name):
print("实例初始化触发__init__")
self.name = name
p = Person("张三") # 自动执行__init__
注意:__init__不是构造方法,只是初始化方法,真正创建对象的是__new__。
6.2 __call__ 可调用对象方法
让实例对象像函数一样直接加括号调用,框架中间件、钩子函数、回调类大量使用。
class Calculator:
def __call__(self, a, b):
return a + b
cal = Calculator()
res = cal(10, 20) # 实例直接调用,触发__call__
print(res)
6.3 __getitem__ 下标取值方法
让自定义类支持下标、切片取值,像列表、字典一样通过 [] 获取数据。
class MyList:
def __init__(self, data):
self.data = data
# 支持下标、切片取值
def __getitem__(self, index):
return self.data[index]
lst = MyList([10, 20, 30, 40])
print(lst[0])
print(lst[1:3])
七、高频面试真题汇总
题目1:实例方法、类方法、静态方法的区别与场景?
答案:实例方法带self、操作实例属性;类方法带cls、操作类属性;静态方法无默认参数,是独立工具方法。分别对应实例逻辑、类通用逻辑、独立工具逻辑。
题目2:@property的作用是什么?
答案:将方法伪装为属性调用,简化语法,支持属性读取、赋值拦截,可实现数据校验、权限控制、代码兼容,是面向对象封装的常用手段。
题目3:__slots__的原理和优缺点?
答案:禁用实例__dict__字典,固定属性列表,大幅降低海量实例内存占用、提升访问速度;缺点是无法动态新增实例属性,灵活性降低,适合批量小对象场景。
题目4:__init__和__call__的作用?
答案:__init__在实例化时触发,用于初始化属性;__call__让实例可被括号调用,实现对象函数化,常用于框架回调、中间件设计。
题目5:Python多继承的查找规则?
答案:遵循MRO广度优先算法,从左到右查找父类方法,解决多继承方法名冲突问题。
八、全文终极背诵总结
1、类与实例:类是抽象模板,实例是具体对象;类属性全局共享,实例属性独立私有,实例赋值类属性会生成同名实例属性。
2、继承多态:继承实现代码复用,支持单继承与多继承(MRO顺序);多态统一调用入口,子类重写方法实现差异化逻辑。
3、@property:方法伪装属性,简洁调用,支持读写拦截、数据校验、权限控制,强化封装特性。
4、三类方法:实例方法操作实例、类方法操作类属性、静态方法为独立工具方法,场景分工明确。
5、__slots__:固定实例属性,取消__dict__,海量实例场景极致优化内存,牺牲动态属性灵活性。
6、核心魔法方法:__init__初始化实例属性,__call__实现实例可调用,__getitem__支持下标切片取值。