Python 用父类初始化子类

Python 用父类初始化子类,python,inheritance,Python,Inheritance,我想有一个家长和一个孩子的班级 使用父实例初始化子类。 我的方式似乎很麻烦(见下文): 我定义了一个staticmethod来提取父级初始化的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,

我想有一个家长和一个孩子的班级 使用父实例初始化子类。 我的方式似乎很麻烦(见下文):

我定义了一个staticmethod来提取父级初始化的
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))
有没有更直接的方法


编辑现在类更简单了

为什么不保存init参数并在
Parent
上创建一个新的绑定方法以
make_child()

演示

使您的父(以及子)构造函数接受更改后的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

我认为您需要将初始化
子对象的概念与从
父对象创建一个对象的概念分开。
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)
如果要对从父对象获取的值进行更改,请在创建子对象之前,在
中将这些更改应用于\u parent

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)

根据您在我原始答案中的评论,我相信您不想将
父类划分为子类
;相反,您只需要备用构造函数

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
如果您确实想要
父类的子类
,则无需放弃任何更改<代码>父项
仅包括适用于所有子项的功能

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

为什么要在父类中进行更改和恢复?为什么不为初始参数(如old_a、old_b)使用实例变量,然后保持正则变量不变?这样,您就可以检查parent.old_a等,但我也会遇到同样的问题:我需要
get_init_params
方法从旧的父对象中提取它们。
get_init_params
方法会稍微简单一点,这对于组织代码没有意义。
change{a,b}
到底在做什么?除非它们是有状态函数,否则此控制流会让您撤消父构造函数中的更改,以便稍后重新进行。。。我想这就是你想要改进的地方。谢谢你的主意。但通常我不希望我的家长班级依赖于孩子们。(例如,没有其他人可以对我的父类进行子类化,因为每个子类都需要一个
make\u child
方法。啊,我理解。但是子类不再是(父类)
实例,因此我没有任何继承。我无法调用
子类。any\u parentmethod()
anymore@ProfHase85为什么不呢?您仍然需要自己定义子类。像以前一样将其设置为
子类(父类)
。在您的解决方案中,子类不会使用正确的父类初始化(因为在child@ProfHase85如果这不能满足您的所有要求,我会对您正在做的事情感到非常困惑=/仍然是同一个问题:如果我有10个孩子,我将不得不在每个孩子身上实现初始化家长的方法。想象一下如果家长初始化签名更改。哦,你的意思是从父级@prophase85初始化。如果这是个问题,你可以将子级的静态方法实现为类方法,并将其放在一个共同的祖先上。你甚至可以使用多重继承。这会在构造函数中应用更改两次-一次是在初始化父级时,一次是在将其属性传递给重写了子类的构造函数——可能是破坏了它。但这就是他应该将行为从init方法中移除的原因。谢谢,这是一种方法,但是如果我想将父类放入
\uuuuuu init\uuuu
方法中,我该怎么办?我的意思是直接调用子类
子类(父类)
你不需要。离开
\uuuu init\uuuu
直接初始化
子级
,使用另一个构造函数,该构造函数需要一个
父级
@jwilner是的,在我看到他的编辑后,我决定忽略对参数进行更改/反转的问题。@ProfHase85,这一点不是用于ch的唯一路径ild类,它将实现最多的代码重用。构造函数不应该仅仅因为它将是实例化对象的主要途径而将行为备份到它中。这正是类级方法的用途……根据他对另一个答案的评论:他应该停止滚动他自己的数据库!:)
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
class Child(Parent):
    def __init__(self, a, b):
        super(Child, self).__init__(a, b)
        # Any Child-specific initialization