Python面向对象内置方法详解:__str__、__del__与__call__

夏知夏
夏知夏
发布时间:2026-10-16 | 6人浏览过
原创

本文深入解析Python面向对象编程中的三个核心内置方法:__str__、__del__和__call__。详细讲解__str__在对象打印时的触发机制与属性查找顺序,__del__在垃圾回收前的执行逻辑,以及__call__如何控制对象与类的调用行为。通过元类自定义__call__方法的示例,揭示类实例化的完整底层流程,帮助开发者掌握Python对象模型的关键细节。

在Python的class类定义中,存在一系列内置方法,例如__call__和__str__等。这些特殊方法在满足特定条件时会自动触发运行,无需手动调用。

接下来将详细介绍几个常用的内置方法及其工作原理。

1、__str__

首先说明其作用:当使用print函数打印对象实例时,会自动触发并运行该方法。

示例1如下:

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
stu1 = Student('xiaoming',18)
print(stu1)      #运行原理就是,先在Student类里找__str__方法,没有就去他的父类找
print(object.__str__(stu1))   #验证了Student的父类里面有__str__方法

其输出结果为:

#<__main__.Student object at 0x0000023A1170C128> #<__main__.Student object at 0x0000023A1170C128>

示例2:

我们可以在Student类中自定义一个__str__方法来进行验证。执行print打印操作时,其原理是调用了__str__方法。

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        print(self.name)
        return '<name:%s age:%s>' %(self.name,self.age)
stu1 = Student('xiaoming',18)
print(stu1)     #这个stu1就是__str__的返回值

输入结果为:

xiaoming <name:xiaoming age:18>

补充说明对象属性查找的顺序:首先查找对象自身的名称空间,若未找到则查找对象对应类的名称空间,最后查找该类的基类的名称空间。

2、__del__方法

该方法的作用是:在删除对象之前自动触发执行。

直接通过代码示例展示:

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __del__(self):
        print('%s 已经被删除' % self.name)
stu1 = Student('xiaoming', 18)
stu2 = Student('zhangsan', 18)
print('主')

其执行结果为:

主 xiaoming 已经被删除 zhangsan 已经被删除

解释为何输出上述结果:这涉及Python解释器的垃圾回收机制。当一个程序运行完毕,Python会回收该程序在内存中产生的数据。当执行到print('主')且后续没有代码执行时,解释器会删除stu1和stu2这两个对象。在删除这两个对象之前,会执行__del__方法,因此出现了上述输出结果。

3、__call__

在调用该对象时(即实例化过程中),会自动运行其类及类的基类中的__call__方法。如果该类中不存在此方法,则该对象是不可调用的。

class Student:   #补充:class Student: 相当于就是 Student = type(类名,该类的基类们,类体代码产生的名称空间)
    pass
Student()

分析如下:一切皆对象,Student本身也是一个对象,它是通过元类type实例化得来的。因此,调用Student()时,实际上是去type元类中查找__call__方法并执行。由于type类中确实包含__call__方法,所以上述代码运行不会出错。

下面通过一个例子来验证上述结论:

class Student:  # (相当于上面例子的type)
    def __init__(self, name, age):
        self.name = name
        self.age = age
stu1 = Student('xiaoming', 18)  # stu1(相当于上面例子的Student)
try:  # 这里我们通过捕捉异常来打印出错原因
    stu1()  # 这里相当于上面Student()
except Exception as e:
    print(e)
    # 打印结果是:'Student' object is not callable
    # “Student”对象不可调用,也就是stu1是不可调用的

结论:通过这两个例子可以得出,只要该对象的类中包含__call__方法,那么该对象就可以被调用,即可以实例化。

该对象实例化的过程,本质上就是运行其类中的__call__方法。

进行验证:该对象实例化,即是运行其类中的__call__方法。

class Teacher:
    def __init__(self, name):
        self.name = name
    def __call__(self, *args, **kwargs):
        print('我被%s调用了' % self.name)
tea1 = Teacher('xiaoming')
tea1()

#输出结果是:我被xiaoming调用了

如何通过元类来控制类的调用?

可以通过在自定义元类中定义__call__方法,来实现对类的调用控制。

1、首先,类的调用原理就是运行元类中的__call__方法。

2、通过__call__方法来实现对对象的初始化操作。

class Mymeta(type):
    def __call__(self, *args, **kwargs):  # self就是Student *args和**kwargs就是Student后面的参数
        # print(self)
        # print(args)
        # print(kwargs)
        obj = self.__new__(self)  # 就是创建一个Student的空对象
        self.__init__(obj, *args, **kwargs)  # 执行__init__方法    这里需要注意查找顺序
        return obj  # 将实例化完的对象返回回去
class Student(object, metaclass=Mymeta):
    def __init__(self, name, age):
        self.name = name
        self.age = age
stu1 = Student('xiaoming', age=18)
print(type(stu1),stu1.__dict__)

这就是类的实例化的整个过程。不过,这是通过自定义元类来控制类的调用,本质上只是在__call__中多写了一些代码而已。

在默认元类type中,必然存在__call__方法。该方法执行时,首先创建一个空对象,随后执行__init__方法。

目前先讲解这三个方法,其他如__dict__、__class__、__name__等属性不再赘述。

到此,这篇关于Python面向对象内置方法梳理讲解的文章就介绍到这了。更多相关Python面向对象内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表