Python中self关键字报错咨询:NameError与TypeError原因解析
搞懂Python中self的工作机制——你的三个代码问题解析
嘿,我来帮你拆解一下这三个代码示例里的问题,核心都是没搞明白self到底是什么、该怎么用~
先明确一个核心知识点:
self是Python类中实例方法的第一个参数,它代表的是类的实例对象本身。只有当你创建了类的实例,并且通过这个实例调用方法时,Python才会自动把这个实例作为self传递给方法。直接在类外瞎用self,或者在类内没实例就调用实例方法,都会出问题。
代码示例1:NameError: name 'self' is not defined
class myClass: def foo(self): print('WORKED') self.foo()
问题出在最后一行的self.foo():这里的self完全是无中生有!self只有在类的实例方法内部才有意义,你在类的定义外面直接写self,Python根本不知道它指代的是哪个实例(甚至连实例都还没创建),自然会报“名字未定义”的错误。
正确写法:先创建类的实例,再通过实例调用方法:
class myClass: def foo(self): print('WORKED') # 创建类的实例 obj = myClass() # 通过实例调用方法,Python会自动把obj作为self传给foo obj.foo()
代码示例2:TypeError: foo() missing 1 required positional argument: 'self'
class myClass: def foo(self): print('WORKED') foo()
你在类的定义内部直接调用了foo(),但foo是一个需要self参数的实例方法——这时候类还没创建任何实例,根本没有可以传给self的对象,所以Python会提示你缺少必要的参数。
正确做法:如果想调用这个方法,要么把调用放在类的其他实例方法里(比如初始化方法__init__),要么创建实例后再调用:
class myClass: def __init__(self): # 在实例方法内部调用,self就是当前实例 self.foo() def foo(self): print('WORKED') # 创建实例时会自动调用__init__,进而执行foo obj = myClass()
代码示例3:输出两次WORKED,但pylint警告
class myClass: def foo(): print('WORKED') foo() myClass.foo()
这里你把foo定义成了没有self参数的方法,相当于把它当成了一个普通函数放在类里面:
- 类在定义的时候,会执行内部的顶级代码,所以
foo()会被调用一次,输出第一个WORKED; - 后面的
myClass.foo()是直接通过类调用这个无参数方法,又输出一次WORKED。
pylint的警告是因为这种写法不符合Python的类方法规范:如果想定义不需要实例的类方法,应该用@classmethod或@staticmethod装饰器:
- 用
@classmethod:参数用cls代表类本身,适合需要访问类属性的场景 - 用
@staticmethod:不需要类或实例参数,就是一个普通函数挂在类下面
规范写法:
class myClass: @classmethod def foo(cls): print('WORKED') myClass.foo() # 只输出一次WORKED
最后再划个重点:
- 实例方法必须带
self参数,只能通过类的实例调用,Python自动传参; - 类方法用
@classmethod装饰,参数是cls,可以通过类或实例调用; - 静态方法用
@staticmethod装饰,无特殊参数,和普通函数类似,挂在类名下而已。
内容的提问来源于stack exchange,提问作者hhilal
相关产品推荐
相关产品推荐

