Python类中__init__非必须,但传参初始化必须定义;self是约定参数,不可省略;类属性与实例属性易混淆,需注意赋值位置;方法须正确声明self、@staticmethod或@classmethod;子类需调用super().__init__()确保父类初始化。

类定义时 __init__ 不是必须的,但没它就无法传参初始化
Python 类可以不写 __init__,这时候实例化 MyClass() 就只是生成一个空对象。但只要你想在创建对象时传入参数(比如 Person("Alice", 25)),就必须定义 __init__,且第一个参数得是 self。
常见错误:把 __init__ 拼错成 __int__ 或 __inint__,运行时不会报错,但参数全被忽略,实例属性一个都不会设上。
-
self是对当前实例的引用,不是关键字,但约定俗成不能换;换成me或this虽然语法通过,但会吓到协作者 - 如果所有参数都有默认值,
__init__可以完全省略参数传入,比如def __init__(self, name=None, age=0): - 别在
__init__里做耗时操作(如读文件、连数据库),实例化就变慢,且异常难调试
实例属性和类属性混用,一改全改
在类体里直接写的变量(如 count = 0)是类属性,所有实例共享;在 __init__ 里用 self.xxx = ... 定义的是实例属性,各管各的。
常见错误:误把本该属于每个实例的字段写成类属性,比如 data = [],结果所有实例往里 append 都在操作同一个列表。
立即学习“Python免费学习笔记(深入)”;
- 判断依据:看赋值位置——类定义缩进内、函数外的是类属性;
__init__或其他方法里带self.前缀的是实例属性 - 类属性适合放常量、配置、计数器(如
created_count),但修改时要用ClassName.attr = ...,而不是self.attr = ...(后者会新建实例属性,遮蔽类属性) - 想让类属性可变又安全?用
@classmethod包裹修改逻辑,避免直接裸写赋值
方法没加 self 参数,调用就报 TypeError: missing 1 required positional argument
普通实例方法必须把 self 当第一个参数,Python 在调用时自动传入当前实例。漏了它,解释器就会把实例当成第一个显式参数,导致“多传一个”。
错误现象:obj.do_something() 报错说缺参数,但你明明没写参数——其实是 self 没占位,Python 把 obj 塞进了第一个形参,后面没东西接了。
- 静态方法用
@staticmethod,类方法用@classmethod,它们不需要self,但得明确标出来,否则一律按实例方法处理 - IDE 通常能标出这种缺失,但命令行运行时才暴露,建议开 PyCharm 或 VS Code 的 Pylint 检查
- 别靠删
self来“修复”报错——那说明你根本没搞清这个方法该属于谁
继承中 super().__init__() 忘调或错调,父类初始化就失效
子类重写了 __init__,又没手动调父类的 __init__,那父类里定义的那些实例属性(比如 self.name)压根不会存在。
错误现象:子类实例访问 obj.parent_attr 报 AttributeError,但父类明明写了初始化逻辑。
- Python 3 中
super()不带参数是安全的,推荐写成super().__init__(...),比ParentClass.__init__(self, ...)更健壮(尤其多重继承) - 如果父类
__init__有必填参数,子类必须传过去;漏传或类型不对,错误发生在父类内部,堆栈可能让你找不到源头 - 不是所有父类都要求调
__init__——比如只定义了类属性、没实例属性的父类,但别猜,看父类源码或文档
__new__ 分配内存 → 执行 __init__ 填充数据。大多数人卡在第二步之后,因为 __new__ 很少动,而 __init__ 写错、漏调、参数错位,都会让对象“看起来建出来了,其实没建好”。







