Python复制在具有自定义_新_方法的类上失败

2024-09-24 02:18:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组特定定义的类(比如彩色大号)和一个泛型类(比如大号)。如果创建泛型类的实例,它可能会返回特定的类。我通过重写泛型类的__new__方法来处理这个问题,该方法检查输入并返回相应的类实例

这适用于对象创建,例如,我可以说

tuba = Tuba('red')
type(tuba)  # will give 'RedTuba'

但是,如果我尝试复制我的tuba,Python会生成一个TypeError,表示__new__未命中1个必需参数。我不太清楚在这种情况下__new__应该如何正确使用

在这种情况下,我需要如何实现__new__以使其正常工作

from copy import copy


class Instrument:
    def __init__(self, kind):
        self.kind = kind


class RedTuba(Instrument):
    # note: RedTuba cannot be derived from Tuba since this is an 
    # abstract example on the actual case I'm having trouble with
    def __init__(self):
        super().__init__(kind='special-red-tuba')


class Tuba(Instrument):
    def __new__(cls, color):
        if color == 'red':
            return RedTuba.__new__(RedTuba)
        return super().__new__(cls)

    def __init__(self, color):
        super().__init__(kind='{}-tuba'.format(color))


r = Tuba('red')
copy(r)  # this works

v = Tuba('violet')
copy(v)  # this does not work

由此产生的错误是

Traceback (most recent call last):
  File "creation.py", line 28, in <module>
    copy(v)
  File "/Users/jul/Envs/latest/lib/python3.7/copy.py", line 106, in copy
    return _reconstruct(x, None, *rv)
  File "/Users/jul/Envs/latest/lib/python3.7/copy.py", line 274, in _reconstruct
    y = func(*args)
  File "/Users/jul/Envs/latest/lib/python3.7/copyreg.py", line 88, in __newobj__
    return cls.__new__(cls, *args)
TypeError: __new__() missing 1 required positional argument: 'color'

Tags: pyselfnewreturninitdefredfile
1条回答
网友
1楼 · 发布于 2024-09-24 02:18:01

试试这样的

from copy import copy
from typing import Optional


class Instrument:
    def __init__(self, kind):
        self.kind = kind


class RedTuba(Instrument):
    # note: RedTuba cannot be derived from Tuba since this is an 
    # abstract example on the actual case I'm having trouble with
    def __init__(self):
        super().__init__(kind='special-red-tuba')


class Tuba(Instrument):
    def __new__(cls, color: Optional[str] = None):
        color_mapper = {
            'red': RedTuba
        }
        if color in color_mapper:
            tuba_cls = color_mapper[color]
            return tuba_cls.__new__(tuba_cls)
        return super().__new__(cls)

    def __init__(self, color):
        super().__init__(kind='{}-tuba'.format(color))

我只在{}中更改了{}

问题正是它所说的,颜色是必需的。现在它是可选的

dunder方法的子类化通常很棘手。如果你不需要的话,尽量不要那样做。但我知道你想要完成什么,这是有道理的

祝你好运

相关问题 更多 >