可以在__setstate__中调用__init__吗?

10 投票
3 回答
1961 浏览
提问于 2025-04-18 05:21

我正在改进一个已经存在的类,这个类在__init__函数中进行一些计算,以确定实例的状态。请问在__getstate__()中调用__init__()来重复使用这些计算,这样做可以吗?

3 个回答

-1

另一种方法是自定义子类中的构造函数类 __init__。理想情况下,最好有一个构造函数类,然后根据你的需要在子类中进行修改。

class Person:
    def __init__(self, name, job=None, pay=0):
        self.name = name
        self.job = job
        self.pay = pay

class Manager(Person):
    def __init__(self, name, pay):                   
        Person.__init__(self, name, 'title', pay)  # Run constructor with 'title'

这样调用构造函数在Python中是一个非常常见的编程模式。Python本身使用继承来查找并在构造时只调用一个 __init__ 方法——也就是在类树中最低的那个。

如果你需要在构造时运行更高层的 __init__ 方法,你必须手动调用它们,通常是通过超类的名称,就像上面的代码所示。这样,你可以增强超类的构造函数,并完全替换子类中的逻辑,以符合你的需求。

正如Jan所建议的,这样做有点棘手,如果在同一个类中调用它,你可能会遇到困难的调试情况。

2

通常来说,最好写一个叫做 __getnewargs__ 的方法。这样,序列化的机制就会自动帮你调用 __init__ 方法。

4

总结一下Kroltan和jonsrharpe的观点:

从技术上讲是可以的

从技术上来说,这样做是可以的,如果你操作得当,可以认为是没问题的。

但实际上有点棘手,最好避免

如果你将来修改代码,碰到__init__的时候,很容易(即使是你自己)忘记在__setstate__中使用它,这样就会陷入难以调试的情况(你会问自己,这个东西是从哪里来的)。

class Calculator():
    def __init__(self):
        # some calculation stuff here
    def __setstate__(self, state)
        self.__init__()

计算的部分最好单独放到另一个共享的方法里:

class Calculator():
    def __init__(self):
        self._shared_calculation()   

    def __setstate__(self, state)
        self._shared_calculation()

    def _shared_calculation(self):
        #some calculation stuff here

这样你就能注意到问题了。

注意:共享方法前面加“_”这个前缀是随意的,你不一定要这样做。

撰写回答