当前位置: 代码网 > it编程>前端脚本>Python > Python中self用法示例详解

Python中self用法示例详解

2026年01月27日 Python 我要评论
前言在 python 中,self并不是语言关键字,而是实例方法中第一个参数的约定名称,指向调用该方法的实例对象。它的显式存在集中体现了 python 的核心设计哲学:显式优于隐式、一切皆对象,以及简

前言

在 python 中,self 并不是语言关键字,而是实例方法中第一个参数的约定名称,指向调用该方法的实例对象。它的显式存在集中体现了 python 的核心设计哲学:显式优于隐式、一切皆对象,以及简洁一致的调用模型。

一、self 的本质是什么

首先要知道的是,self 不是 python 的关键字,也没有任何特殊语法含义。它只是实例方法中第一个参数的惯用名称,用于表示“当前对象的实例引用”。

例如:

class dog:    def bark(self):        print("woof!")

当我们执行:

d = dog()d.bark()

python 实际上在内部做了如下调用:

dog.bark(d)

也就是说,self 就是调用该方法的对象实例 d。因此,bark() 方法能通过 self 访问对象的属性和其他方法。

二、为什么必须显式写出 self

很多面向对象语言(如 java、c++)中有一个隐藏参数 this,它在方法中自动存在。python 没有这样做,原因在于它的“一切皆对象”哲学:方法本质上就是函数对象,只是存放在类的命名空间中。

python 不希望让“方法”成为一种特殊语法,而是通过普通函数与对象绑定的机制来实现方法调用。这种设计让函数、类、实例三者的关系更透明、更灵活。

python 不会自动注入“实例引用”,必须显式声明第一个参数,社区约定俗成地命名为 self。

这使得方法调用规则简单且一致:任何函数若绑定到实例上,其第一个参数都会接收实例对象。

三、方法的绑定机制:self 如何被传入

要理解 self,首先需要了解方法在 python 中是如何被绑定的。

当我们通过 实例.方法 的方式访问一个方法时,python 会执行以下步骤:

1、在实例所属的类中查找该方法对应的函数对象。

2、如果找到该函数对象 f,则触发其 __get__() 方法(这是通过描述符机制实现的)。

3、__get__() 方法会返回一个绑定方法(bound method) 对象,该对象内部保存了当前实例的引用。

4、当我们调用这个绑定方法时,python 会自动将保存的实例作为第一个参数(即 self)传入原函数。

示例说明:

class a:    def show(self, x):        print(self, x)
a = a()a.show(10)

上述调用实际上等价于:

a.show(a, 10)

也就是说:

🔹通过实例访问方法时,会得到一个已绑定实例的“绑定方法”,调用时自动传入 self。

🔹通过类访问方法时,得到的仍是一个普通函数,调用时需要显式传入实例作为 self。

四、三种方法绑定的比较

python 中存在三种类型的方法绑定方式:

方法类型

装饰器

第一个参数

隐式绑定对象

用途

实例方法

(无)self

实例

访问或修改实例状态

类方法

@classmethodcls

类对象

操作类本身(如工厂方法)

静态方法

@staticmethod(无)

工具函数,不依赖实例或类

示例:

class example:    def instance_method(self):        print("实例方法", self)
    @classmethod    def class_method(cls):        print("类方法", cls)
    @staticmethod    def static_method():        print("静态方法")

调用方式:

obj = example()obj.instance_method()      # 自动传入实例example.class_method()     # 自动传入类example.static_method()    # 不传入任何对象

五、self 在继承与多态中的作用

self 永远指向实际调用该方法的对象。即使方法定义在父类中,被子类继承后调用时,self 仍然指向子类实例。

示例:

class animal:    def speak(self):        print("animal speaking:", type(self).__name__)
class cat(animal):    pass
class dog(animal):    pass
cat().speak()  # animal speaking: catdog().speak()  # animal speaking: dog

animal.speak() 方法内部访问的 self,在运行时绑定为 cat 或 dog 实例,这就是多态(polymorphism)的基础。

六、super() 与 self 的协作

在继承中使用 super() 时,python 会根据方法解析顺序(mro)找到父类的方法,但 self 不会变。

class base:    def show(self):        print("base:", self)
class sub(base):    def show(self):        print("sub before")        super().show()   # 调用 base.show(self)        print("sub after")
s = sub()s.show()

输出:

sub beforebase: <__main__.sub object ...>sub after

注意:super().show() 虽然调用了父类方法,但 self 仍然是 sub 实例。

七、常见错误与误区

(1)方法定义中遗漏 self 参数

class bad:    def func():        print("missing self")
bad().func()  # typeerror: bad.func() takes 0 positional arguments but 1 was given

异常原因:通过实例调用方法时,python 会自动将实例本身作为第一个参数传入,但该方法定义没有预留接收该参数的位置。

(2)误以为 self 是固定关键字

实际上,self 只是约定俗成的参数名,可以使用任意名称替代:

class a:    def f(this):        print(this)

但这样做违反了 python 社区的编码规范,会严重损害代码的可读性和一致性。按照 pep 8 约定,始终使用 self 表示实例方法的第一个参数,使用 cls 表示类方法的第一个参数。

(3)混淆类属性与实例属性

class counter:    count = 0            # 这是类属性,所有实例共享
    def __init__(self):        self.count += 1  # 这里实际创建了一个新的实例属性!

如需修改类属性,应显式引用类名:

counter.count += 1       # 正确修改类属性

八、self 的设计哲学

从语言设计的角度看,self 的设计体现了 python 的几项核心理念。

(1)显式优于隐式(explicit is better than implicit)

self 作为方法的第一个参数明确写出,清晰地表明了实例的传递过程,避免了像其他语言中隐藏的 this 指针所带来的隐式行为。

(2)一切皆对象

在 python 中,方法本身也是对象。具体来说,是绑定到类中的函数对象。方法的绑定过程通过描述符协议实现,而非特殊的语法规则,这体现了 python 对象模型的一致性。

(3)简洁一致的调用模型

无论是 obj.method() 还是 class.method(obj),本质上都是将实例作为第一个参数传递给函数。这种设计消除了方法调用与函数调用之间的概念差异,保持了语义的一致性。

小结

在 python 中,self 是实例方法中第一个参数的约定名称。通过 self,实例方法能够访问和修改对象的状态,并天然支持继承与多态特性。即使在通过 super() 调用父类方法时,self 依然正确地指向最初发起调用的实际对象。

因此,深入理解 self 不仅有助于掌握方法绑定的底层机制,更是透彻理解 python 面向对象编程设计思想的重要基石。

到此这篇关于python中self用法示例详解的文章就介绍到这了,更多相关python self用法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com