Python中self用法示例详解

作者:

文章目录
  • 在 Python 中,self 并不是语言关键字,而是实例方法中第一个参数的约定名称,指向调用该方法的实例对象。它的显式存在集中体现了 Python 的核心设计哲学:显式优于隐式、一切皆对象,以及简洁一致的调用模型。
  • 首先要知道的是,self 不是 Python 的关键字,也没有任何特殊语法含义。它只是实例方法中第一个参数的惯用名称,用于表示“当前对象的实例引用”。 例如: class Dog: def bark(self): print(“Woof!”) 当我们执行: d = Dog()d.bark() Python 实际上在内部做了如下调用: Dog.bark(d) 也就是说,self 就是调用该方法的对象实例 d。因此,bark() 方法能通过 self 访问对象的属性和其他方法。
  • 很多面向对象语言(如 Java、C++)中有一个隐藏参数 this,它在方法中自动存在。Python 没有这样做,原因在于它的“一切皆对象”哲学:方法本质上就是函数对象,只是存放在类的命名空间中。 Python 不希望让“方法”成为一种特殊语法,而是通过普通函数与对象绑定的机制来实现方法调用。这种设计让函数、类、实例三者的关系更透明、更灵活。 Python 不会自动注入“实例引用”,必须显式声明第一个参数,社区约定俗成地命名为 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 实例 访问或修改实例状态 类方法 @classmethod cls 类对象 操作类本身(如工厂方法) 静态方法 @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 仍然指向子类实例。 示例: 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() 时,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 的设计体现了 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用法内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python中的self用法详解 全面理解Python中self的用法 Python类中self参数用法详解 python类参数self使用示例 详解Python self 参数 python定义类self用法实例解析 python中self原理实例分析
  • 目录
    • 前言
    • 一、self 的本质是什么
    • 二、为什么必须显式写出 self
    • 三、方法的绑定机制:self 如何被传入
    • 四、三种方法绑定的比较
    • 五、self 在继承与多态中的作用
    • 六、super() 与 self 的协作
    • 七、常见错误与误区
    • 八、self 的设计哲学
    • 小结

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

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

    例如:

    class Dog:    def bark(self):        print("Woof!")

    当我们执行:

    d = Dog()d.bark()

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

    Dog.bark(d)

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

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

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

    Python 不会自动注入“实例引用”,必须显式声明第一个参数,社区约定俗成地命名为 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

    实例

    访问或修改实例状态

    类方法

    @classmethod cls

    类对象

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

    静态方法

    @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 仍然指向子类实例。

    示例:

    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() 时,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 的设计体现了 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用法内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Python中的self用法详解
    • 全面理解Python中self的用法
    • Python类中self参数用法详解
    • python类参数self使用示例
    • 详解Python self 参数
    • python定义类self用法实例解析
    • python中self原理实例分析

    站内搜索