You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数的方法,相当于把它当成了一个普通函数放在类里面:

  1. 类在定义的时候,会执行内部的顶级代码,所以foo()会被调用一次,输出第一个WORKED;
  2. 后面的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 12:59:05