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

Имея объект 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, которые используют один и тот же базовый класс, объекты принимают одинаковый предопределенный набор аргументов.


person Davor Lucic    schedule 18.09.2010    source источник


Ответы (1)


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

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

person Alex Martelli    schedule 18.09.2010