Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在不使用super的情况下设置_new__返回的值的类?_Python_Factory - Fatal编程技术网

Python 如何在不使用super的情况下设置_new__返回的值的类?

Python 如何在不使用super的情况下设置_new__返回的值的类?,python,factory,Python,Factory,我希望B成为某个类a的子类,并且我希望覆盖a.。\uuuuu new\uuuu1。通常,我的代码具有以下基本结构: 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。(注意:su

我希望
B
成为某个类
a
的子类,并且我希望覆盖
a.。\uuuuu new\uuuu
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)中的省略号。
中的省略号不必表示与
B中省略号表示的项目相同的项目。
的签名。)

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

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

        # modify ret as needed

        return ret  # type(ret) is A
…那么
类型(B(…)
将是
A
,而不是
B

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


1我知道通常不需要重写父类的
\uuuuu new\uuuu
,但这里我感兴趣的是需要重写的不常见情况。

您可以将实例的属性设置为传递到
\uu new\uuu
中的
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'>
2
真的
真的
不过,这也有一些局限性。报告列出了它们:

当对象结构为 一样。我希望对结构等效性的测试足够严格。 仅当新旧类型满足以下条件时,才允许分配:

  • 基本尺寸相同
  • 具有相同的项目大小
  • 具有相同的dict偏移量
  • 有同样的弱点
  • 具有相同的GC标志位
  • 有一个相同的公共基,除了dict和weaklist(可能以相同的偏移量单独添加)
    (两种类型)

如果您在任何一个类上都定义了相同的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu插槽,则它们还需要具有相同的
。实际上,这通常只是意味着这两个类都需要用Python实现。尝试使用常规Python类和
int
tuple
或其他用C实现的东西来实现这一点是不可能的。

您是否坚持使用
\uuuu new\uuu
,还是愿意接受其他解决方案?