Python类中避免使用self引用是否为最佳实践?变量使用疑问
嘿,这两个问题问到点子上了,作为天天跟Python类打交道的开发者,我来给你掰扯清楚~
绝对不是!反而会给你的代码埋下可读性和维护性的大坑。
Python类的设计逻辑里,self是用来明确区分实例变量(每个对象独有的数据)和局部变量(方法内部临时使用的变量)的核心标识。如果你刻意避免用self,会出现两种混乱的情况:
- 你本来想定义一个实例变量,结果写成了方法内的局部变量,导致其他方法根本访问不到这个值,排查问题时要绕好几个弯;
- 不小心把类变量(所有实例共享的变量)和局部变量混为一谈,团队协作时其他开发者看到没有
self的变量,完全搞不清它的作用域,理解成本直接拉满。
举个反例:
class MyList: def __init__(self): # 这里没加self,count是__init__的局部变量 count = 0 self.head = None def size(self): # 这里的count如果是局部变量,和__init__里的count完全没关系 return count
这个代码里size()根本拿不到__init__里的count,直接会报错。所以遵循Python的约定,用self明确标记实例变量,才是真正的最佳实践。
先拆解第一个小问题:为什么count、current不用self也能跑?大概率是两种情况:
- 这俩是类变量:你在类的顶层定义了
count和current(比如class MyList: count = 0),所有实例共享这个值,所以不管用self.count还是直接写count,访问的都是同一个类变量; - 你在
size()方法内部重新定义了count和current作为局部变量,刚好和你以为的实例变量重名了,但其实这俩和实例本身没有任何关系,只是方法里临时用的变量。
你可以做个小测试:创建两个实例,修改其中一个的count,如果另一个的count也跟着变,那就是类变量;如果不变,那size()里的count就是局部变量,和实例无关。
而self.head必须用self.的原因很简单:head是实例变量,每个实例的head都是独立的(比如链表的头节点,每个链表实例的头肯定不一样)。它是在__init__或者其他实例方法里用self.head = ...定义的,只有通过self.才能访问到当前实例的这个变量——如果不加self.,Python会认为你要访问一个未定义的局部变量,直接抛出NameError。
再说说“非必要场景下使用self.是不是不良实践”:首先得明确,不存在“非必要”的情况——
- 如果是实例变量,
self.是必须的,不用才会出错; - 如果是类变量,虽然可以用
self.访问,但更推荐用类名.变量名(比如MyList.count),这样能明确告诉其他开发者“这是个类变量,所有实例共享”; - 如果是方法内部的局部变量,绝对不能加
self.,加了反而会把它变成实例变量(如果之前没定义的话),导致数据混乱。
所以核心是:用self.标记实例变量,用类名.标记类变量,局部变量不用前缀——这样代码清晰,不会出歧义,根本不存在“不良实践”的说法,反而能避免很多bug。
内容的提问来源于stack exchange,提问作者user9352220

