Как создать новый экземпляр того же класса, что и другой объект? - PullRequest
4 голосов
/ 18 сентября 2010

Имея объект x, который является экземпляром некоторого класса, как создать новый экземпляр того же класса, что и объект x, без импорта этого всех возможных классы в том же пространстве имен, в котором мы хотим создать новый объект того же типа и используя isinstance, чтобы определить правильный тип.

Например, если x - десятичное число:

>>> from decimal import Decimal
>>> x = Decimal('3')
>>> x
Decimal('3')

как создать новый экземпляр Decimal. Я думаю, что очевидная вещь, которую нужно сделать, была бы одна из этих:

>>> type(x)('22')
Decimal('22')
>>> x.__class__('22')
Decimal('22')

Поскольку __class__ не будет работать на int, например:

>>> 1.__class__
  File "<stdin>", line 1
    1.__class__

Является ли хорошей практикой использование type для достижения этой цели, или есть ли другие способы или больше предостережений при использовании этого подхода для создания новых объектов?

Примечание : Был удален ответ, который дал правильный способ получить __class__ из int.

>>> (1).__class__
<type 'int'>

Вариант использования

Вопрос в основном теоретический, но я сейчас использую этот подход с Qt для создания новых экземпляров QEvent. Например, поскольку объекты QEvent используются обработчиком событий приложения для отправки события в QStateMachine, необходимо создать новый экземпляр события, в противном случае вы получите ошибку времени выполнения, поскольку C ++ объект удаляется.

И поскольку я использую пользовательские подклассы QEvent, которые все используют один и тот же базовый класс, таким образом, объекты принимают один и тот же предопределенный набор аргументов.

1 Ответ

6 голосов
/ 18 сентября 2010

Вызов type(x) - определенно канонический способ создания нового экземпляра того же типа, что и x. Однако, какие аргументы для передачи этому вызову не являются заданными, потому что «подпись» (количество и типы аргументов, передаваемых в вызове) меняется с каждым другим типом; поэтому, если вы не имеете представления о том, каким может быть тип, вам потребуется больше самоанализа для этой цели (а также какое-то правило или эвристика о том, какие все аргументы вы хотите передать после того, как определите, например, что вы можете передать любое число от 0 до 3, и что имена необязательных аргументов / ключевых слов: 'y', 'z', 't' ... очевидно, здесь невозможно установить общее правило!).

Итак, не могли бы вы уточнить (как только тип для определения будет легко определен ;-), как вы собираетесь решать сложные части вашей проблемы, о которых вы даже не упомянули? Какие ограничения вы можете принять на подпись типа? Вам нужно выполнить некоторые проверки работоспособности или это нормально, просто вызвать TypeError, вызвав с неправильным видом или числом аргументов? И т. Д., И т. Д. ... без дополнительной информации такого рода ваш вопрос просто не поддается доказательству того, что на самом деле можно использовать в реальном мире! -)

...