【问题标题】:Python casting base class object to subclass using dataclassPython使用数据类将基类对象转换为子类
【发布时间】:2021-03-20 22:10:18
【问题描述】:

我有一个 Employee 基类和一个 Manager 子类。子类接受一个 Employee obj 并将其转换为 Manager。

下面的代码可以正常工作,但是我正在尝试确定如何使用数据类创建相同的代码。

class Employee:
    def __init__(self, id: int, name: str):
        self.id = id
        self.name = name

class Manager(Employee):
    def __init__(self, employee: Employee, region: str):
        super().__init__(**vars(employee))
        self.region = region

e1 = Employee(1, 'Bob')
e2 = Employee(2, 'Sally')

# Sally gets promoted to manager of southwest region
e2 = Manager(e2, 'southwest')

这是我目前所拥有的,我不确定如何传递所有必需的参数。

@dataclass
class Employee:
    id: int
    name: str

@dataclass
class Manager(Employee):
    region: str
    def __new__(cls, employee: Employee, region: str):
        obj = object.__new__(cls)
        super().__init__(obj, **vars(employee))
        return obj

e2 = Employee(2, 'Sally')
>>> Manager(e2, region='southwest')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'name'

【问题讨论】:

    标签: python python-dataclasses


    【解决方案1】:

    我不确定所有 __new__ 元类黑客的目的是什么,但您很少需要在 Python 中覆盖 __new__,这也不例外。

    @dataclass
    class Employee:
        id: int
        name: str
    
    @dataclass
    class Manager(Employee):
        region: str
    
    e2 = Employee(2, 'Sally')
    m2 = Manager(2, 'Sally', 'southwest')
    

    数据类就是这样;用于存储数据的类。数据类的继承就像您期望的那样工作。只需继承即可。

    如果您仍然希望将Employee 作为参数,您可以使用__init__ 而不是__new__

    @dataclass
    class Employee:
        id: int
        name: str
    
    @dataclass
    class Manager(Employee):
        region: str
        def __init__(self, employee: Employee, region: str):
            super().__init__(**vars(employee))
            self.region = region
    

    【讨论】:

    • 理想情况下,我想将 e2 obj 传递给 Manager 类并分配属性,而不必指定每个属性。尤其是在 Employee 具有数百个属性的情况下。
    • 我尝试使用__new__,因为它在__init__ 之前被调用,所以它让我有机会将e2.__dict__ 传递给super。
    • 然后查看我的编辑。在我看来,__init__ 仍然可以正常工作。如果这对您不起作用,请随时澄清,我们可以再看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2013-05-08
    相关资源
    最近更新 更多