用parent初始化子类

时间:2015-05-07 15:13:30

标签: python inheritance

我想要父母和子女 使用父实例初始化子类。 我的方式似乎很麻烦(见下文):

我定义了一个静态方法来提取父级初始化的init参数:

class Parent(object):
    @staticmethod
    get_init_params(parent_obj):
        a = parent_obj.a
        b = parent_obj.b
        return (a, b)

    def __init__(self, a, b):
        self.a = a
        self.b = b

class Child(Parent):
    def __init__(self, parent):
        super(Parent, self).__init__(*get_init_params(parent))

是否有更直接的方式?

编辑现在课程更简单

4 个答案:

答案 0 :(得分:5)

我认为您希望将初始化 Child对象的概念与<{>创建的概念从Parent分开。 get_init_params只是增加了一层你不需要的复杂性;直接访问属性。

class Child(Parent):
    @classmethod
    def from_parent(cls, parent):
        return cls(parent.a, parent.b)

    def __init__(self, a, b):
        super(Child, self).__init__(a, b)
        # Note: the fact that yo have to do this,
        # or not call the parent's __init__ in the first
        # place, makes me question whether inheritance
        # is the right tool here.
        self.a = revert_change(self.a)
        self.b = revert_change(self.b) 

p = Parent(3, 5)
c1 = Child.from_parent(p)
c2 = Child(6, 6)

如果您对来自父级的值进行了更改,请在创建to_parent对象之前将其应用于Child

def from_parent(cls, parent):
    return cls(revert_change(parent.a), revert_change(parent.b))
    # Or, if you save the original values
    # return cls(parent.orig_a, parent.orig_b)

答案 1 :(得分:1)

根据您在原始答案中的评论,我相信您不想继承Parent;相反,你只需要替代构造函数。

class Parent(object):

    # The basic initializer; just use whatever values are
    # passed directly to it
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @classmethod
    def type_1(cls, a, b):
        return cls(change_a1(a), change_b1(b))

    @classmethod
    def type_2(cls, a, b):
        return cls(change_a2(a), change_b2(b))

    # etc

如果你真的想要一个Parent的子类,那么就没有必要退出任何变化; Parent仅包含适用于所有子项的功能。

class Child(Parent):
    def __init__(self, a, b):
        super(Child, self).__init__(a, b)
        # Any Child-specific initialization

答案 2 :(得分:0)

为什么不保存init参数并在Parentmake_child()上创建新的绑定方法?

class Parent(object):
    def __init__(self, *args, **kwargs):
        self.init_args = {'args':args, 'kwargs':kwargs}
        self.children = list()
        ...  # whatever else a Parent does

    def make_child(self, child_cls, *args, **kwargs):
        if args is None:
            args = self.init_args['args']
        if kwargs is None:
            kwargs = self.init_args['kwargs']
        child = child_cls(self, *args, **kwargs)
        self.children.append(child)
        return child


class Child(Parent):
    def __init__(self, parent, *args, **kwargs):
        self.parent = parent
        ...  # whatever else a Child does

样本

>>> p = Parent()
>>> c = p.make_child(Child)
>>> c in p.children
True

答案 3 :(得分:-1)

让你的父(以及子)构造函数改变a和b。您应该尽可能少地使用init方法中的行为。创建一个不改变a和b的类方法,更改它们,然后将类构造函数应用于它们 - 这对父和子都有好处。然后在子类上编写一个静态方法,该子类接受父对象,并将其更改的a和b属性传递给期望更改a和b的init方法。

class Parent(object):
    @classmethod 
    def from_unchanged(cls, a, b):
        changed_a = change_a(a) 
        changed_b = change_b(b) 
        return cls(a, b) 

    @classmethod
    def from_parent(cls, parent):
        return cls(parentchanged_a, parentchanged_b) 

    def __init__(self, changed_a, changed_b) :
        selfchanged_a = changed_a
        selfchanged_b = changed_b