python - 如何在不使用 super 的情况下设置 __new__ 返回值的类别?

标签 python factory

我要B成为某个类的子类 A ,我想覆盖 A.__new__ 1。通常,我的代码将具有以下基本结构:

class B(A):
    def __new__(cls, ...):
        ret = super(B, cls).__new__(cls, ...)

        # modify ret as needed

        return ret  # type(ret) is cls

    # ...

这样,type(B(...))确实是B . (注意:super(B, cls).__new__(cls, ...) 中的省略号不需要与 B.__new__ 的签名中的省略号代表的项目相同。)

但现在假设我想使用某些工厂方法/函数 返回的值A_Factory (返回 A 类型的对象)作为变量 ret 的起始值在构造函数中。如果我只是这样编码:

class B(A):
    def __new__(cls, ...):
        ret = A_Factory(...)

        # modify ret as needed

        return ret  # type(ret) is A

...然后type(B(...))将是 A , 不是 B .

设置 ret 类的正确方法是什么?在 B.__new__ 的第二个版本中以上,type(B(...))B ,更一般地说,对于任何直接或间接子类 CB , type(C(...))C


1 我知道通常不需要覆盖父类的 __new__ ,但在这里我对需要的不常见情况感兴趣。

最佳答案

您可以设置 __class__实例的属性是传递给 __new__cls:

class A(object):
    def __init__(self):
        self.x = 2

def A_Factory():
    return A() 

class B(A):
    def __new__(cls):
        ret = A_Factory()

        ret.__class__ = cls  # Override the class.

        return ret  # type(ret) is cls

class C(B):
    pass


if __name__ == "__main__":
    b = B() 
    print(b.x)
    print(type(b))
    print(isinstance(b, B)) 
    print(isinstance(b, A))
    c = C()
    print(type(C))

输出:

2
<class '__main__.B'>
True
True
<class '__main__.C'>

不过,这有一些限制。 commit that added the ability to assign to __class__列出它们:

Make __class__ assignment possible, when the object structures are the same. I hope the test for structural equivalence is stringent enough. It only allows the assignment if the old and new types:

  • have the same basic size
  • have the same item size
  • have the same dict offset
  • have the same weaklist offset
  • have the same GC flag bit
  • have a common base that is the same except for maybe the dict and weaklist (which may have been added separately at the same offsets
    in both types)

它们还需要具有相同的 __slots__,如果您在任一类上定义了它们。实际上,这通常只意味着这两个类都需要在 Python 中实现。尝试使用常规 Python 类和 inttuple 或用 C 实现的其他内容不太可能奏效。

关于python - 如何在不使用 super 的情况下设置 __new__ 返回值的类别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26282774/

相关文章:

laravel-5 - laravel 模型工厂种子从现有生成

python - Twisted : Same Service, 不同端口中的多个同时工厂和协议(protocol)

python - pandas, numpy 四舍五入到最接近的 100

python - Django - 如何使用 sorl-thumbnail?

singleton - "Singleton"工厂,好还是坏?

c++ - 通过 operator new 定义简单对象工厂的正确语法

python - 通过将第一个列表中的第一行项目与第二个列表中的项目进行比较来创建新列表

python - 如何从numpy矩阵中排除元素

python - 使用 if 检查实例

java - 使用工厂方法模式