python类重写__new__,返回其他类的实例

新手上路,请多包涵

上代码:
class A:

"""通过__new__返回其他的类"""

def __init__(self, data=None, **kwargs):
    self.data = data

def __new__(cls, *args, **kwargs):
    if kwargs.pop("another", False):
        # 返回B类的实例
        instance = B(*args, **kwargs)
        return instance
    return super().__new__(cls)

class B(A):

created_num = 0     #计数总共创建了多少实例
instance_list = []
def __init__(self, name=None, **kwargs):
    # 将实例保存在instance_list中
    self.__class__.instance_list.append(self)
    # 对实例赋值id
    self.instance_id = self.created_num
    # 每创建一个实例,实例数 + 1
    self.__class__.created_num += 1
    self.name = name
    super().__init__(**kwargs)

@property
def self_cls(self):
    return self.instance_id, self.__class__.created_num

if name == "__main__":

b = A(data=0, name='ty', another=True)
print()

如上,我通过传递参数another=True,使A返回一个B类的实例,在print()处打断点,期望的结果是b.self_cls == (0, 1), b.instance_list中只有一个实例对象。
可是事与愿违:
image.png
结果表明创建了两个实例,且当前实例是第二个(b.self_cls == (1, 2),但instance_list中的两个实例对象却又是同一个(内存地址相同),百思不得其解,希望能有大神帮忙解答,在此谢过。

阅读 1.6k
1 个回答

把断点打在B.__init__
第一次调用栈是

B.__init__
A.__new__
main

第二次是

B.__init__
main

也就是说在A.__new__ return后, B.__init__又被调用了一次,
而正常的python对象创建的流程就是先new在init, 很合理.

如果想调用一次的话,改成下面这样就行了

    def __new__(cls, *args, **kwargs):
        if kwargs.pop("another", False):
            # 返回B类的实例
            -- instance = B(*args, **kwargs)
               -- return instance
            ++ return super().__new__(B)
        return super().__new__(cls)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题