如何用另一个对象替换__init __()中的实例?

sne*_*eak 17 python oop

我在ClassA中调用构造函数,并且如果满足某个条件,则希望生成的对象具有不同的类(ClassB).我试着更换的第一个参数__init __()(在下面的例子中"自我") __init __(),但它似乎并没有做我想做的.

在主要:

import ClassA

my_obj = ClassA.ClassA(500)
# unfortunately, my_obj is a ClassA, but I want a ClassB!
Run Code Online (Sandbox Code Playgroud)

在ClassA/__ init__.py中:

import ClassB

class ClassA:
    def __init__(self,theirnumber):
        if(theirnumber > 10):
            # all big numbers should be ClassB objects:
            self = ClassB.ClassB(theirnumber)
            return
        else:
            # numbers under 10 are ok in ClassA.
            return
Run Code Online (Sandbox Code Playgroud)

在ClassB/__ init__.py中:

class ClassB:
    pass
Run Code Online (Sandbox Code Playgroud)

Dav*_*d Z 33

你需要__new__()那个.(并且你还需要使它成为一个新式的类,假设你使用Python 2,通过子类化object.)

class ClassA(object):
    def __new__(cls,theirnumber):
        if theirnumber > 10:
            # all big numbers should be ClassB objects:
            return ClassB.ClassB(theirnumber)
        else:
            # numbers under 10 are ok in ClassA.
            return super(ClassA, cls).__new__(cls, theirnumber)
Run Code Online (Sandbox Code Playgroud)

__new__()作为类实例化过程的一部分运行之前__init__().基本上__new__()是实际创建新实例的内容,__init__()然后调用它来初始化其属性.这就是为什么你可以使用__new__()但不能__init__()改变创建的对象的类型:一旦__init__()启动,对象已经被创建,并且改变它的类型为时已晚.(嗯......不是真的,但是这会变成非常神秘的Python黑魔法.)请参阅文档.

但在这种情况下,我会说工厂功能更合适,比如说

def thingy(theirnumber):
    if theirnumber > 10:
        return ClassB.ClassB(theirnumber)
    else:
        return ClassA.ClassA(theirnumber)
Run Code Online (Sandbox Code Playgroud)

顺便说一下,请注意,如果你按照我__new__()上面所做的操作,如果ClassB返回a,则不会调用实例的__init__()方法!如果返回的对象是包含该方法的类的实例(此处),则Python仅调用.这是支持工厂功能方法的另一个论点.ClassB__init__()__new__()__new__()ClassA


Sam*_*lan 15

我建议使用工厂模式.例如:

def get_my_inst(the_number):
   if the_number > 10:
       return ClassB(the_number)
   else:
       return ClassA(the_number)

class_b_inst = get_my_inst(500)
class_a_inst = get_my_inst(5)
Run Code Online (Sandbox Code Playgroud)


Ned*_*der 12

不要试图歪曲构造函数的目的:使用工厂函数.调用一个类的构造函数并返回一个不同类的实例是一种引起混淆的可靠方法.

  • 我认为我可以设法保持不融合,他们. (7认同)