Python面向对象-面向对象进阶
2025-9-2
| 2025-9-5
Words 7019Read Time 18 min
type
status
date
slug
summary
tags
category
icon
password

📝 面向对象的成员

1、变量(Data Members)

1.1、总览速查表

名称
定义位置
归属
访问方式
生命周期
类变量
类体里,方法外
类本身
类名.变量 或 实例.变量
程序运行期间
实例变量
方法内,self. 前缀
每个实例
实例.变量
实例创建→销毁
局部变量
方法/函数内部
栈帧
仅函数内部
调用→返回
私有变量
__var_var
实例/类
类内 self.__var,类外受限
同实例变量

1.2、类变量(Class Variable)

  1. 定义位置:位于 类体内部、所有方法外部(即直接写在类名下,且前面无 self.)。
  1. 生命周期
      • 创建:类被 定义/导入 时立即生成,直到程序结束才销毁。
      • 销毁:进程结束或类被显式 del 时。
  1. 共享性
      • 所有实例和类本身共享同一份内存
      • 通过 类名.变量实例.变量 都可访问;实例修改会 创建同名实例变量 覆盖,但类变量本身不变。

1.3、实例变量(Instance Variable)

  1. 定义位置:在 实例方法内部 且通过 self.变量名 = 值 的形式绑定,通常放在 __init__ 中,也允许在其它方法里动态添加。
  1. 生命周期
      • 创建:实例化对象(obj = Class(...))时随 __init__ 或后续赋值产生。
      • 销毁:该对象被垃圾回收(无引用)时自动释放。
  1. 隔离性
      • 每个实例拥有独立的一份内存
      • 实例之间互不影响;修改一个实例变量不会影响其它实例。

1.4、局部变量(local variable)

  1. 定义位置:出现在类的方法体内部(包括实例方法、类方法、静态方法)或函数体内部,且前面没有 self.类名前缀
  1. 生命周期
      • 创建:执行到变量赋值语句时。
      • 销毁:方法/函数执行结束(return 或抛出异常)即被垃圾回收。
  1. 隔离性
      • 每次方法调用都重新创建,不共享给其它调用或实例。
      • 作用域仅限于当前栈帧,外部无法访问。

1.5、私有变量(private variable)

  1. 定义位置:在类的方法内部,以 双下划线前缀 __变量名单下划线前缀 _变量名 绑定到实例或类本身。
      • __var(双下划线)触发「名称重整」,类外无法直接访问;
      • _var(单下划线)仅约定私有,仍可直接访问。
  1. 生命周期:与所属实例或类的生命周期一致
      • 创建:实例化或类定义时赋值;
      • 销毁:实例/类被垃圾回收时释放。
  1. 隔离性
      • 作用域:仅在类内部可见(双下划线通过名称重整强制隔离)。
      • 每实例/每类独立一份,与其他实例/类互不干扰。

1.6、五大易错点

  1. 同名掩盖:读时“就近”,写时“新建”
    1. 易错:误以为 a.x = 99 会修改类变量。
  1. __私有 名称重整:读/写都要用重整后的名字
    1. 子类内部读写双下划线变量,必须加 _父类__前缀
  1. 继承链查找顺序:只读不改时遵循 MRO
    1. C.x = 2 则会在 C 类本身 新建变量,不会改动 P.x
  1. 实例写类变量:需显式指定类名
    1. 可变类变量陷阱:读引用,写重绑
      1. 若执行 Box.items = [7] 则重绑到新列表,旧列表与实例无影响。

    2、方法(Method Members)

    2.1、总览速查表

    方法类型
    装饰器
    默认第一个形参
    归属
    访问场景
    典型用途
    实例方法
    self(当前对象)
    实例
    需要对象状态
    读写属性、业务逻辑
    类方法
    @classmethod
    cls(当前类)
    无需对象但需类级数据
    工厂方法、修改类变量
    静态方法
    @staticmethod
    既不需要对象也不需要类
    工具函数、校验逻辑

    2.2、实例方法(Instance Method)

    1. 定义在类体内部、未加任何装饰器的普通函数;其第一个形参必须是 self(名字可改,但约定为 self),代表当前对象本身。
    1. 绑定与调用创建:类被定义后,函数对象即被绑定为实例方法。调用:
        • 实例对象调用:obj.method()
        • 类名手动调用:Class.method(obj, *args)(极少用)。
    1. 作用域与访问权限作用域:方法体内部可直接访问并修改实例变量self.var)和类变量Class.varself.__class__.var)。无法访问其他实例的私有变量(除非显式传参)。
    1. 生命周期与实例对象同生同灭;实例销毁后,该方法仍可被类再次调用(但需新实例)。
    1. 示例
      1. 总结:实例方法以 self 为入口,只能通过对象调用,用于读写该对象自身状态或调用类级资源。

      2.3、类方法(Class Method)

      1. 定义与语法用装饰器 @classmethod 声明,第一个形参必须是 cls(约定俗成),指向当前类对象本身。
        1. 绑定与调用绑定:类加载时自动把函数包装成类方法对象,与实例无关。调用方式
            • 类名调用:Foo.cm(x)
            • 实例调用:obj.cm(x)(等价于 Foo.cm(x),因为 cls=Foo)。
        1. 作用域与权限可读写类变量 (cls.var),无法直接访问实例变量(除非显式传入实例)。可继承:子类调用时 cls 就是子类,天然支持多态。
        1. 生命周期与类同生同灭;类被垃圾回收后方法才消失。
        1. 典型用途工厂方法:根据参数返回不同实例。修改类级配置。类级工具函数。
        1. 示例:
          1. 总结:类方法以 cls 为入口,操作类本身或提供类级工厂,与具体实例无关,可被类或实例调用。

          2.4、静态方法(@staticmethod)

          1. 定义用 @staticmethod 装饰,无默认形参(既无 self 也无 cls),本质上只是一个放在类命名空间里的普通函数
            1. 绑定与调用不绑定任何对象或类,不会自动传入 self/cls。调用方式
                • 类名调用:Foo.util(1,2)
                • 实例调用:obj.util(1,2)(与类名调用等价)。
            1. 作用域与隔离性不能直接访问实例变量或类变量(除非显式传参)。仅借类的命名空间做逻辑归类,与类/实例状态完全解耦
            1. 生命周期与类同生同灭;类被卸载时方法随之消失。
            1. 典型用途工具/校验函数(如日期格式检查)。与类逻辑相关、但无需类或实例状态的辅助方法。
            1. 示例
              1. 总结:静态方法既不依赖实例不依赖类,只是借类的“文件夹”存放工具函数,调用时与普通函数无异。

              3、属性(Property Members)

              💡
              在 Python 面向对象中,“属性”可以分成两大实现路线:
              1. “定义变量”——最朴素的类属性 / 实例属性;
              1. “基于装饰器”——把方法伪装成属性(@property@staticmethod@classmethod 等)。

              3.1、基于定义变量:类属性 & 实例属性

              • 类属性:所有实例共享;
              • 实例属性:每个对象独立一份;
              • 读写规则:读时“实例→类”,写时“实例新建同名变量”。

              3.2、基于装饰器:把方法“伪装”成属性

              1. @property(只读属性 / 可读写属性)
                  • 访问方式像变量c.area),背后其实是方法调用;
                  • 支持 getter / setter / deleter,实现“数据验证 + 懒加载”。
              1. @staticmethod@classmethod(类级属性伪装)
                  • 静态方法:纯粹工具函数,放在类命名空间内;
                  • 类方法:可读写类变量、充当工厂函数。

              3.3、两条路线的对比速查表

              特性
              定义变量
              @property / @staticmethod / @classmethod
              语法
              attr = value
              @decorator + 函数
              是否可验证
              ✅(getter/setter)
              是否可懒加载
              ✅(计算属性)
              是否可读写类级数据
              类变量可
              类方法可
              调用成本
              方法调用,略高
              • 想“存数据”——用定义变量(类 / 实例属性)
              • 想“数据 + 逻辑封装”——用 @property@staticmethod@classmethod 把方法伪装成属性,实现验证、懒加载、工厂等高级行为。

              3.4、拓展

              1. property()方法
                1. 作用:把 getter / setter / deleter 三个函数一次性封装成同名属性,实现「数据验证、懒加载、只读/只写」等高级封装,而不暴露内部存储。
                  参数
                  默认值
                  描述
                  fget
                  None
                  读属性时调用的函数(getter)
                  fset
                  None
                  写属性时调用的函数(setter)
                  fdel
                  None
                  删除属性时调用的函数(deleter)
                  doc
                  None
                  属性的文档字符串
              1. @property@xxx.setter@xxx.deleter 装饰器

                📝 面向对象的成员修饰符

                1、成员修饰符速查表

                可见级别
                语法
                内部/外部访问
                机制
                典型场景
                公开 Public
                name
                ✅/✅
                无限制
                普通属性/方法
                受保护 Protected
                _name
                ✅/✅(约定)
                仅 IDE/文档提示
                子类继承用
                私有 Private
                __name
                ✅/❌(改名)
                名称重整 _Class__name
                完全隐藏
                只读属性
                @property
                ✅读/❌写
                方法伪装属性
                计算/验证
                类私有
                __name__
                ✅/✅
                魔术方法
                系统钩子

                2、完整示例:

                3、使用与陷阱演示

                📝 对象嵌套

                1、相关概念

                1.1、一个类的属性 不是普通数字/字符串,而是另一个对象 —— 这就是嵌套。

                1.2、三种常见套法:

                套法
                大白话
                例子
                生命周期
                组合(整体-部分)
                “我死你随”
                班级里有学生,班级解散,学生也没了
                同生同死
                关联
                “咱俩认识”
                学生持有班级引用,但班级可以换
                可换可空
                依赖
                “临时用一下”
                学生进班级前才 new Classes()
                用完即弃

                2、一张图秒懂

                3、代码对照

                3.1、 组合(最紧密)

                3.2、关联(松一点,可换班级)

                3.3、依赖(最松,临时用)

                4、生命周期对比表

                关系
                对象诞生
                对象销毁
                换对象
                组合
                整体 __init__ 里一起 new
                整体销毁,部分一起没
                不支持
                关联
                外部 new 后传进来
                整体销毁,部分仍活
                随时换
                依赖
                方法里临时 new
                方法结束即没
                每次新

                📝 特殊成员

                1、__init__,初始化方法

                1.1、规则一句话

                子类没定义 __init__ ⇒ 沿 MRO 找第一个定义了 __init__ 的类,把它的实现拿来用;如果这一路谁都没写,最终落到 object.__init__

                1.2、代码验证

                1.3、菱形继承再看 MRO

                MRO: D → B → C → A → object

                1.4、小结

                • 子类不写 __init__ ≠ 不执行初始化;
                • 解释器按 MRO 顺序复用第一个遇到的 __init__
                • 参数列表必须和“被选中的那个 __init__”完全匹配,否则调用方抛 TypeError
                • 想“自动转发全部参数”就自己在子类里写 super().__init__(*args, **kwargs)

                2、__new__,构造方法

                💡
                new真正负责“造壳”的构造器,它创建实例并决定返回什么;init 只是给空壳“填肉”的初始化器。

                2.1、定义与签名

                2.2、调用顺序

                2.3、典型用途

                • 继承不可变类型(int、str、tuple)
                • 单例模式
                • 对象池 / 缓存
                • 元类自定义实例化

                2.4、示例

                1. 继承不可变类型
                  1. 单例

                    2.5、注意

                    • 必须返回实例;返回 None 或类型不匹配会抛 TypeError
                    • 仅当返回实例且类型正确时,__init__ 才会被调用。

                    3、__call__

                    3.1、作用与语法

                    实例可以像函数一样被调用——实现 可调用对象(callable instance)

                    3.2、定义示例

                    3.3、与函数的区别

                    • 可携带状态(如上例 count)。
                    • 可继承、组合、多态,天然面向对象。

                    3.4、典型场景

                    • 计数器、缓存器、策略对象、装饰器类。
                    • 框架钩子(如 torch.nn.Moduleforward 实质由 __call__ 触发)。

                    3.5、判断与调试

                    3.6、总结

                    __call__ 让实例“变身”函数,既能保存状态又能像函数一样使用,是 Python 实现可调用对象的魔法钩子。

                    4、__str__

                    4.1、作用与语法

                    当对象被 print()str() 或 f-string 调用时,Python 自动触发 __str__ 方法,返回面向终端用户的可读字符串

                    4.2、使用示例

                    4.3、与 repr 区别

                    • str:面向用户,简洁、美观。
                    • repr:面向开发者,通常返回能重建对象的表达式字符串。若只实现 __str__,则 repr(obj) 会回退到默认格式;反之亦然。

                    4.4、总结

                    实现 __str__ 让你的对象在打印时直接呈现自定义、友好的文字信息。

                    5、__dict__

                    5.1、作用

                    • 实例字典:保存实例的所有可写属性(不含 slots、描述符、类变量)。
                    • 类字典:保存类的属性、方法、类变量等。
                    • 本质是 普通 dict,可动态增删改查。

                    5.2、语法示例

                    5.3、常见操作

                    5.4、注意点

                    • 使用 __slots__ 的类实例无 __dict__
                    • 类变量不会出现在实例 __dict__ 中。
                    • 修改 __dict__立即生效,但破坏封装,慎用于生产代码。

                    5.5、总结

                    __dict__ 是实例/类的「属性仓库」,可读写、可遍历,是 Python 动态特性的核心接口之一。

                    6、__getitem__/__setitem__/__delitem__

                    💡
                    这三个魔法方法让自定义对象支持「索引/切片」语法,像列表、字典一样用 obj[key]obj[key] = valuedel obj[key]

                    6.1、方法签名

                    6.2、最小可运行示例(列表包装器)

                    6.3、切片也走同一路径

                    • obj[1:3] 等价于 obj.__getitem__(slice(1, 3, None))
                    • obj[1:3] = [4,5] 等价于 obj.__setitem__(slice(1,3), [4,5])

                    6.4、常见陷阱

                    场景
                    说明
                    KeyError / IndexError
                    自己决定抛什么异常;Python 规范期望 KeyError 用于 dict-like,IndexError 用于 list-like
                    只读容器
                    不实现 setitemdelitem 即可
                    不可切片的键
                    getitem 里手动判断 isinstance(key, slice)

                    6.5、总结

                    实现 __getitem__/__setitem__/__delitem__ 就能把自定义对象变成「可索引、可赋值、可删除」的容器,语法与内置容器完全一致。

                    7、__enter__/__exit__

                    💡
                    实现这两个方法后,实例就能与 with 语句配合,自动完成资源获取与清理,形成上下文管理器(Context Manager)。

                    7.1、协议规则

                    方法
                    触发时机
                    返回值
                    异常处理
                    enter(self)
                    with 代码块开始时
                    任意对象(赋给 as 变量)
                    exit(self, exc_type, exc_val, exc_tb)
                    with 代码块结束时(无论正常或异常)
                    True 吞掉异常,False 继续传播
                    接收异常三元组

                    7.2、最小可运行示例

                    运行输出

                    7.3、异常处理示例

                    7.4、总结

                    实现 __enter__/__exit__,你的对象就能被 with 托管,自动完成“资源获取—使用—释放”三步曲,异常也能优雅收尾。

                    8、__add__

                    8.1、作用

                    当对象出现在 + 左侧时,解释器自动调用 obj.__add__(other),返回“加法”结果;若未实现,则尝试调用 other.__radd__(obj)

                    8.2、签名

                    8.3、完整示例

                    8.4、类型检查

                    8.5、总结

                    重写 __add__ 即可让自定义对象支持 + 运算符,实现“向量、金额、矩阵”等加法语义。

                    9、__iter__

                    9.1、作用

                    使自定义对象可迭代for ... in obj:list(obj) 等)。
                    解释器在需要迭代时,先调用 iter(obj)obj.__iter__(),该方法必须返回迭代器(即实现了 __next__ 的对象)。

                    9.2、最小实现

                    9.3、快捷写法:让对象自己就是迭代器

                    9.4、总结

                    只要类提供 __iter__ 并返回一个带 __next__ 的迭代器,就能让实例直接用于 for 循环、推导式、解包等所有迭代场景。

                    📝 魔术方法(Magic / Special Methods)速查表

                    1、对象生命周期

                    方法
                    触发时机
                    典型用途
                    __new__(cls, ...)
                    构建空实例
                    单例、不可变类型扩展
                    __init__(self, ...)
                    填充初始状态
                    常规初始化
                    __del__(self)
                    实例将被回收
                    释放非内存资源(文件、句柄)

                    2、运算符重载

                    类别
                    方法
                    表达式
                    比较
                    __eq__, __ne__, __lt__, __le__, __gt__, __ge__
                    a == b, a < b ...
                    算术
                    __add__, __sub__, __mul__, __truediv__, __floordiv__, __mod__, __pow__
                    a + b, a - b ...
                    位运算
                    __and__, __or__, __xor__, __lshift__, __rshift__
                    a & b, a \| b ...
                    反向/就地
                    __radd__, __iadd__ ...
                    1 + obj, obj += 1
                    一元
                    __neg__, __pos__, __invert__
                    -obj, ~obj

                    3、容器协议(列表/字典/集合行为)

                    方法
                    表达式/作用
                    备注
                    __len__
                    len(obj)
                    长度
                    __getitem__(self, key)
                    obj[key]
                    支持切片 slice
                    __setitem__(self, key, val)
                    obj[key] = val
                    __delitem__(self, key)
                    del obj[key]
                    __contains__(self, item)
                    item in obj
                    成员测试
                    __iter__(self)
                    for i in obj
                    迭代器协议
                    __reversed__(self)
                    reversed(obj)
                    反向迭代

                    4、可调用对象

                    方法
                    表达式
                    说明
                    __call__(self, *args, **kw)
                    obj(*args, **kw)
                    让实例像函数一样使用

                    5、上下文管理器(with 语句)

                    方法
                    表达式
                    说明
                    __enter__(self)
                    with obj as x:
                    进入上下文
                    __exit__(self, exc_type, exc_val, exc_tb)
                    离开 with
                    清理资源、异常抑制

                    6、字符串/字节表示

                    方法
                    表达式
                    说明
                    __str__(self)
                    str(obj) / print(obj)
                    用户友好字符串
                    __repr__(self)
                    repr(obj) / 调试台
                    开发者字符串,力求 eval(repr(obj))==obj
                    __format__(self, fmt)
                    f"{obj:fmt}"
                    自定义格式化
                    __bytes__(self)
                    bytes(obj)
                    字节序列

                    7、描述符协议(@property 底层)

                    方法
                    触发
                    说明
                    __get__(self, obj, owner)
                    读取属性
                    实现 property、缓存等
                    __set__(self, obj, val)
                    设置属性
                    可写描述符
                    __delete__(self, obj)
                    删除属性
                    可删除描述符

                    8、异步协议

                    方法
                    表达式
                    说明
                    __await__
                    await obj
                    awaitable 对象
                    __aiter__, __anext__
                    async for
                    异步迭代器
                    __aenter__, __aexit__
                    async with
                    异步上下文

                    9、复制与序列化

                    方法
                    表达式
                    说明
                    __copy__, __deepcopy__
                    copy.copy(obj) / copy.deepcopy(obj)
                    浅/深拷贝
                    __reduce__, __reduce_ex__
                    pickle.dumps(obj)
                    pickle 序列化钩子

                    10、抽象基类钩子(部分)

                    方法
                    说明
                    __subclasshook__
                    issubclass 自定义判断
                    __instancecheck__
                    isinstance 自定义判断
                  2. 开发
                  3. Python
                  4. Python面向对象-面向对象基础Python数据类型-基础数据类型-Number 数字、bool 布尔、complex 复数
                    Loading...
                    Catalog
                    0%