Python 如何从超类的实例创建子类的实例?

Python 如何从超类的实例创建子类的实例?,python,class,initialization,Python,Class,Initialization,我上了两门课,一个是家长课,一个是孩子课。我想知道的是,是否可以使用父类初始化子类。这是我的代码: class Pc: def __init__(self, brand, processor, price): self.brand = brand self.processor = processor self.price = price class Laptop(Pc): def __init__(self,brand,proc

我上了两门课,一个是家长课,一个是孩子课。我想知道的是,是否可以使用父类初始化子类。这是我的代码:

class Pc:

    def __init__(self, brand, processor, price):
        self.brand = brand
        self.processor = processor
        self.price = price

class Laptop(Pc):
    def __init__(self,brand,processor,price, battery):
        Pc.__init__(self,brand,processor,price)
        self.battery = battery
现在,我可以使用以下命令初始化Laptop类:

b = Laptop('brand','processor','price')
但这对我来说似乎没有多大用处,我的老师也没有很好地解释。我很想知道是否有可能做这样的事情:

a = Pc("brand","processor","price")
b = Laptop(a, "battery")
当我用我的代码尝试这个时,我得到了一个错误。甚至可以这样做吗?

您可以:

class Laptop(Pc):
    def __init__(self, pc, battery):
        Pc.__init__(self, pc.brand, pc.processor, pc.price)
        self.battery = battery
这将初始化从您给构造函数的
pc
参数继承的属性

如果希望能够使用short或long方法,则应定义构造函数以获取关键字参数,然后使用
If
语句调用
Pc.\uuu init\uuuu()
,具体取决于所使用的表单。

您可以执行以下操作:

class Laptop(Pc):
    def __init__(self, pc, battery):
        Pc.__init__(self, pc.brand, pc.processor, pc.price)
        self.battery = battery
这将初始化从您给构造函数的
pc
参数继承的属性


如果您希望能够使用short或long方法,则应定义构造函数以获取关键字参数,然后使用
If
语句调用
Pc.\uuu init\uuuu()
,具体取决于所使用的表单。

您使用的方式有些粗俗:

import copy
a = Pc("brand","processor","price")
b = copy.deepcopy(a)
b.__class__ = Laptop()
b.battery = battery

你用一种有点粗俗的方式:

import copy
a = Pc("brand","processor","price")
b = copy.deepcopy(a)
b.__class__ = Laptop()
b.battery = battery

python中没有内置的机制来实现您想要的功能,因此您必须自己完成,或者找到第三方解决方案

对此,我可能采取的一个好方法是在超类上添加一个类方法,该方法可以克隆您的对象:

class Pc:

    @classmethod
    def clone(cls, target, *extra_args, **extra_kwargs):
        return cls(
            target.brand, target.processor, target.price, *extra_args,
            **extra_kwargs)

    def __init__(self, brand, processor, price):
        self.brand = brand
        self.processor = processor
        self.price = price


class Laptop(Pc):

    def __init__(self, brand, processor, price, battery):
        super(Laptop, self).__init__(brand, processor, price)
        self.battery = battery


a = Pc("brand","processor","price")
b = Laptop.clone(a, 'battery')

print(b.battery)
但您可能会发现初始化参数开始出现问题。我建议将
\uuuu init\uuuu()
所需的参数保持在最低限度,然后配置必要的属性:

a = Pc()
a.brand = 'brand'
# etc.

python中没有内置的机制来实现您想要的功能,因此您必须自己完成,或者找到第三方解决方案

对此,我可能采取的一个好方法是在超类上添加一个类方法,该方法可以克隆您的对象:

class Pc:

    @classmethod
    def clone(cls, target, *extra_args, **extra_kwargs):
        return cls(
            target.brand, target.processor, target.price, *extra_args,
            **extra_kwargs)

    def __init__(self, brand, processor, price):
        self.brand = brand
        self.processor = processor
        self.price = price


class Laptop(Pc):

    def __init__(self, brand, processor, price, battery):
        super(Laptop, self).__init__(brand, processor, price)
        self.battery = battery


a = Pc("brand","processor","price")
b = Laptop.clone(a, 'battery')

print(b.battery)
但您可能会发现初始化参数开始出现问题。我建议将
\uuuu init\uuuu()
所需的参数保持在最低限度,然后配置必要的属性:

a = Pc()
a.brand = 'brand'
# etc.

这有几种选择

  • 如果要保留当前行为,在添加新行为时,可以使用*arg,例如

    class Laptop(Pc):
        def __init__(self, *argv ):
            if len(argv) == 4: #the current one
                brand, processor, price, battery = argv
            elif len(argv) == 2: #the new one
                pc, battery = argv
                brand, processor, price = pc.brand, pc.processor, pc.price
            else:
                raise TypeError
        Pc.__init__(self,brand,processor,price)
        self.battery = battery    
    
    并尽可能简单地使用

    a = Pc("brand","processor","price")
    b = Laptop(a, "battery")
    
  • 创建一个类方法来处理此情况

    class Laptop(Pc):
    
        def __init__(self,brand,processor,price, battery):
            Pc.__init__(self,brand,processor,price)
            self.battery = battery
    
        @classmethod
        def from_pc_and_battery(cls, pc, battery):
            return cls( pc.brand, pc.processor, pc.price, battery)
    
    用这个,就是这样

    a = Pc("brand","processor","price")
    b = Laptop.from_pc_and_battery(a, "battery")
    

  • 这有几种选择

  • 如果要保留当前行为,在添加新行为时,可以使用*arg,例如

    class Laptop(Pc):
        def __init__(self, *argv ):
            if len(argv) == 4: #the current one
                brand, processor, price, battery = argv
            elif len(argv) == 2: #the new one
                pc, battery = argv
                brand, processor, price = pc.brand, pc.processor, pc.price
            else:
                raise TypeError
        Pc.__init__(self,brand,processor,price)
        self.battery = battery    
    
    并尽可能简单地使用

    a = Pc("brand","processor","price")
    b = Laptop(a, "battery")
    
  • 创建一个类方法来处理此情况

    class Laptop(Pc):
    
        def __init__(self,brand,processor,price, battery):
            Pc.__init__(self,brand,processor,price)
            self.battery = battery
    
        @classmethod
        def from_pc_and_battery(cls, pc, battery):
            return cls( pc.brand, pc.processor, pc.price, battery)
    
    用这个,就是这样

    a = Pc("brand","processor","price")
    b = Laptop.from_pc_and_battery(a, "battery")
    

  • 您可以定义
    def\uuuu init\uuu(self,pc,battery):
    然后从
    pc
    参数中复制
    pc
    属性。错误是您定义了
    Laptop.\uuu init\uuuu
    以接收4个参数,但只给了它两个参数。。您需要重新定义函数以获取要传递的参数您可以使用*argv修改laptop init,并根据您有多少个参数以某种方式工作,或者为这个特殊的对象创建一个classmethod作为一个替代构造函数。当您只需要一个对象时,强迫您创建两个对象通常被认为是糟糕的设计。你只需要制作
    电脑
    来制作
    笔记本电脑
    ,然后你就会把它扔掉。
    Pc
    本身并不代表任何东西,将Pc“变成”笔记本电脑也没有任何意义。对我来说,这似乎是继承和组合的(糟糕)组合。你可以定义
    def\uuuuu init\uuuuuuuuuuu(自我、Pc、电池):
    然后从
    Pc
    参数中复制
    Pc
    属性。错误是您定义了
    Laptop.\uuuuu init\uuuu
    以接收4个参数,并且只给了它两个参数。。您需要重新定义函数以获取要传递的参数您可以使用*argv修改laptop init,并根据您有多少个参数以某种方式工作,或者为这个特殊的对象创建一个classmethod作为一个替代构造函数。当您只需要一个对象时,强迫您创建两个对象通常被认为是糟糕的设计。你只需要制作
    电脑
    来制作
    笔记本电脑
    ,然后你就会把它扔掉。
    Pc
    本身并不代表任何东西,将Pc“变成”笔记本电脑也没有任何意义。在我看来,这似乎是继承和组合的(糟糕)组合。