Что вы пытаетесь сделать, это заблуждение.
Если вы хотите получить копию, просто используйте copy
или deepcopy
.
Если вы хотите объекты стиля JavaScript, создайте класс root, который вы можете клонировать или, лучше, переосмыслить свой код на Python вместо JavaScript.
Если вы хотите полнофункциональный клонирование стиля JavaScript даже для встроенных функций, вы не можете этого сделать.
Кроме того, имейте в виду, что основными мотивами использования шаблона прототипа на языках, отличных от прототипов, таких как Java и C++, являются (a), чтобы избежать стоимости new
при подключении объекта и (b), чтобы добавить различные методы или атрибуты для разных экземпляров. Для первого вы не избегаете стоимости, и в любом случае это не имеет значения в Python. Для последнего это уже легко добавлять методы и атрибуты в экземпляры в Python, и клонирование не облегчает его каким-либо образом.
Я знаю, что есть что-то другое происходит с числовыми типами, по сравнению с другими встроенных типов ...
Нет, различие здесь не цифры по сравнению с последовательностями, это неизменные типы против изменяемые:
>>> id(tuple())
4298170448
>>> id(tuple())
4298170448
>>> id(tuple(()))
4298170448
>>> id(tuple([]))
4298170448
Кроме того, он не имеет ничего общего с int
или tuple
конструктор будучи фантазии. Если значение не кэшируются в любом месте, даже повторное буквальным получит новый экземпляр каждый раз, когда:
>>> id(20000)
4439747152
>>> id(20000)
4439747216
небольшие целые числа, пустой кортеж, и значения не-assginable магических констант предварительно кэшируются запускать. Короткие строки обычно проходят интернированные. Но точные детали зависят от реализации.
Итак, как это влияет на вас?
Ну, клонирование неизменяемых типов бессмысленно. По определению, это неизменная копия одной и той же вещи, так что может это сделать?
Между тем, типы, которые не используют __dict__
для их хранения не может быть клонирован таким образом (являются ли они встроенные типы, типы, которые используют слоты, типы, которые генерируют свои атрибуты динамически, ...). В некоторых случаях вы получите ошибку, а в других - неправильное поведение.
Таким образом, если по «последовательности, отображение и числовых типов» включить встроенные команды, как int
и list
, типы STDLIB как Decimal
и deque
или общих типов третьих сторон, таких как gmpy.mpz
или blist.sorteddict
, то этот механизм не будет работать.
Кроме того, даже если вы могли клонировать встроенные классы, вы не можете добавлять новые атрибуты к ним:
>>> a = []
>>> a.foo = 3
AttributeError: 'list' object has no attribute 'foo'
Так что, если вы получили эту работу, опять же, в любом случае это было бы бесполезно.
Между тем, вызывая object.__new__
вместо type(instance).__new__
может вызвать множество проблем для различных классов. Некоторые из них, например __dict__
, предоставят вам сообщение об ошибке, но вы не можете рассчитывать на это в каждом случае.
Существуют и другие, менее серьезные проблемы с идеей. Например:
>>> class Foo(object):
... def __init__(self):
... self.__private = 3
>>> foo = Foo()
>>> foo.__private
3
>>> bar = clone(foo)
>>> bar.__private
AttributeError: 'Foo' object has no attribute '__private'
>>> bar._Foo__private
3
Я не знал об этом модуле и освещал обзор исходного кода. Спасибо. При отражении нет смысла предоставлять клон простых неизменяемых типов - например, числовых типов. Функция deepcopy имеет специальные корпуса для встроенных типов для их обработки. – Owen
@ Owen Правильно, но стоит помнить, что глубокая копия может быть медленнее, чем прямое кодирование из-за этих особых случаев - проверьте, что http://writeonly.wordpress.com/2009/05/07/deepcopy-is-a-pig -for-simple-data/ – pkacprzak