🧩 「类」全景速通:从 `class` 到 `@dataclass` 的一次看懂!

37 阅读2分钟

不是“面向对象八股”,不是“Java 式模板”,
self__slots__,从“继承陷阱”到“元类黑魔法”,

微信图片_20251014151033_10_20.jpg

① 一句话定义:类 = 模板 + 工厂 🏭

类是对象的模板,对象是类的实例。
类比:类 = 饼干模具,对象 = 饼干


② 基本语法:5 分钟写个类 📝

class Dog:
    """狗狗模板"""
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        return f"{self.name}: 汪汪!"

# 实例化
d = Dog("Lucky", 3)
print(d.bark())  # Lucky: 汪汪!

口诀:__init__ 是构造器,self 是实例本身”


③ 成员分类:一张图记牢 🗺️

类型写法归属调用
实例属性self.x = 1对象obj.x
类属性cls.x = 1Class.x
实例方法def foo(self):对象obj.foo()
类方法@classmethodClass.foo()
静态方法@staticmethodClass.foo()

④ 实战:类属性计数器 ⚡️

class Student:
    _count = 0  # 类属性

    def __init__(self, name):
        self.name = name
        Student._count += 1

    @classmethod
    def how_many(cls):
        return cls._count

print(Student.how_many())  # 0
Student("Alice"); Student("Bob")
print(Student.how_many())  # 2

结论:类属性 = 全实例共享,实例属性 = 各管各


⑤ 私有化:双下划线陷阱 🕳️

class Bag:
    def __init__(self): self.__items = []  # 伪私有
    def add(self, item): self.__items.append(item)

b = Bag(); b.add("book")
print(b.__items)  # AttributeError: 'Bag' object has no attribute '__items'
print(b._Bag__items)  # ['book']  ← 真名暴露!

结论:__x 是名字粉碎,不是真私有!


⑥ 魔法方法:10 个必背 ✨

方法作用示例
__init__构造器def __init__(self):
__str__字符串return f"{self.name}"
__len__len(obj)return self.size
__eq__obj1 == obj2return self.id == other.id
__iter__for i in objyield self.data
__getitem__obj[key]return self.data[key]
__call__obj()return self.compute()
__enter__with objreturn self
__exit__with 结束cleanup()
__slots__限制属性__slots__ = ('x', 'y')

⑦ 性能加速:__slots__ 省内存 🚀

class Point:
    __slots__ = ('x', 'y')  # 无 __dict__
    def __init__(self, x, y): self.x = x; self.y = y

p = Point(1, 2)
print(p.__dict__)  # AttributeError: 'Point' object has no attribute '__dict__'

结论:百万实例 → 内存 ↓30%,速度 ↑10%


⑧ 现代写法:@dataclass 冻结 🧊

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: int
    y: int

p = Point(1, 2)
p.x = 3  # dataclasses.FrozenInstanceError

结论:需要字段名 + 类型提示 → 用 frozen dataclass 代替裸 tuple


⑨ 元类黑魔法:类工厂 🧙‍♂️(彩蛋)

class Meta(type):
    def __new__(mcs, name, bases, attrs):
        attrs['_count'] = 0
        return super().__new__(mcs, name, bases, attrs)

class MyClass(metaclass=Meta):
    pass

print(MyClass._count)  # 0

结论:元类 = 类的模板,AOP 利器


⑩ 趣味实战:元组深拷贝调试器(10 行)

import copy, json

def debug_copy(obj):
    """打印对象及其一层子对象的 id"""
    print(f"Root id: {id(obj)}")
    if hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes)):
        for i, item in enumerate(obj):
            print(f"  [{i}] id: {id(item)} -> {type(item)}")

# 使用
a = [1, [2, 3]]
b = copy.deepcopy(a)
debug_copy(a)
debug_copy(b)

🏁 一句话口诀(背它!)

“类是模板,self 是实例,魔法方法变身对象行为,
**类属性共享,实例属性私有,dataclass 冻结,元类造工厂!”**🎵