Python Сбой копирования в классе с пользовательским методом __new__ - PullRequest
0 голосов
/ 05 апреля 2020

У меня есть набор определенных c определенных классов (скажем, цветные тубы) и общий c класс (скажем, туба). Если создается экземпляр класса generi c, он может вернуть указанный класс c. Я справился с этим, переопределив метод __new__ класса generi c, который проверяет ввод и возвращает соответствующий экземпляр класса.

Это работает для создания объекта, например, я могу сказать

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

Однако, если я пытаюсь скопировать мою тубу, 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'

1 Ответ

0 голосов
/ 05 апреля 2020

Попробуйте что-то вроде этого.

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))

Я только изменил __new__ в Tuba.

Проблема именно в том, что он говорит, цвет был необходим. Теперь это необязательно.

Подклассы более сложных методов часто бывают хитрыми. Постарайтесь не делать этого, если вам это не нужно. Но я вижу, что вы пытаетесь выполнить sh, и это имеет смысл.

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...