파이썬에서 객체의 복사본을 어떻게 만들 수 있습니까?
객체의 사본을 만들고 싶습니다. 새 객체가 이전 객체의 모든 속성 (필드 값)을 갖기를 원합니다. 그러나 나는 독립적 인 물건을 갖고 싶습니다. 따라서 새 객체의 필드 값을 변경하면 이전 객체에 영향을 미치지 않아야합니다.
완전히 독립적 인 객체 사본을 얻으려면 copy.deepcopy()
함수를 사용할 수 있습니다 .
얕고 깊은 복사에 대한 자세한 내용은이 질문에 대한 다른 답변 과 관련 질문에 대한이 답변 의 좋은 설명을 참조하십시오 .
파이썬에서 객체의 복사본을 어떻게 만들 수 있습니까?
따라서 새 객체의 필드 값을 변경하면 이전 객체에 영향을 미치지 않아야합니다.
그러면 변경 가능한 객체를 의미합니다.
파이썬 3에서리스트는 copy
메소드를 얻습니다 (2에서는 슬라이스를 사용하여 복사본을 만듭니다).
>>> a_list = list('abc')
>>> a_copy_of_a_list = a_list.copy()
>>> a_copy_of_a_list is a_list
False
>>> a_copy_of_a_list == a_list
True
얕은 사본
얕은 복사본은 가장 바깥 쪽 컨테이너의 복사본입니다.
list.copy
얕은 사본입니다.
>>> list_of_dict_of_set = [{'foo': set('abc')}]
>>> lodos_copy = list_of_dict_of_set.copy()
>>> lodos_copy[0]['foo'].pop()
'c'
>>> lodos_copy
[{'foo': {'b', 'a'}}]
>>> list_of_dict_of_set
[{'foo': {'b', 'a'}}]
내부 객체의 사본이 없습니다. 그것들은 같은 객체입니다-그래서 그들이 변형되면, 변화는 두 컨테이너 모두에 나타납니다.
딥 카피
딥 카피는 각 내부 객체의 재귀 적 카피입니다.
>>> lodos_deep_copy = copy.deepcopy(list_of_dict_of_set)
>>> lodos_deep_copy[0]['foo'].add('c')
>>> lodos_deep_copy
[{'foo': {'c', 'b', 'a'}}]
>>> list_of_dict_of_set
[{'foo': {'b', 'a'}}]
변경 사항은 원본에만 반영되지 않고 사본에만 반영됩니다.
불변의 객체
불변 개체는 일반적으로 복사 할 필요가 없습니다. 실제로, 당신이 시도하면, 파이썬은 당신에게 원래 객체를 줄 것입니다 :
>>> a_tuple = tuple('abc')
>>> tuple_copy_attempt = a_tuple.copy()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'copy'
튜플에는 복사 방법이 없으므로 슬라이스로 시도해 보겠습니다.
>>> tuple_copy_attempt = a_tuple[:]
그러나 우리는 그것이 같은 대상이라는 것을 알았습니다.
>>> tuple_copy_attempt is a_tuple
True
문자열과 유사하게 :
>>> s = 'abc'
>>> s0 = s[:]
>>> s == s0
True
>>> s is s0
True
copy
방법 이 있지만 냉동 세트의 경우 :
>>> a_frozenset = frozenset('abc')
>>> frozenset_copy_attempt = a_frozenset.copy()
>>> frozenset_copy_attempt is a_frozenset
True
변경 불가능한 객체를 복사하는시기
변경 가능한 내부 객체를 복사해야하는 경우 변경 불가능한 객체 를 복사 해야 합니다.
>>> tuple_of_list = [],
>>> copy_of_tuple_of_list = tuple_of_list[:]
>>> copy_of_tuple_of_list[0].append('a')
>>> copy_of_tuple_of_list
(['a'],)
>>> tuple_of_list
(['a'],)
>>> deepcopy_of_tuple_of_list = copy.deepcopy(tuple_of_list)
>>> deepcopy_of_tuple_of_list[0].append('b')
>>> deepcopy_of_tuple_of_list
(['a', 'b'],)
>>> tuple_of_list
(['a'],)
As we can see, when the interior object of the copy is mutated, the original does not change.
Custom Objects
Custom objects usually store data in a __dict__
attribute or in __slots__
(a tuple-like memory structure.)
To make a copyable object, define __copy__
(for shallow copies) and/or __deepcopy__
(for deep copies).
from copy import copy, deepcopy
class Copyable:
__slots__ = 'a', '__dict__'
def __init__(self, a, b):
self.a, self.b = a, b
def __copy__(self):
return type(self)(self.a, self.b)
def __deepcopy__(self, memo): # memo is a dict of id's to copies
id_self = id(self) # memoization avoids unnecesary recursion
_copy = memo.get(id_self)
if _copy is None:
_copy = type(self)(
deepcopy(self.a, memo),
deepcopy(self.b, memo))
memo[id_self] = _copy
return _copy
Note that deepcopy
keeps a memoization dictionary of id(original)
(or identity numbers) to copies. To enjoy good behavior with recursive data structures, make sure you haven't already made a copy, and if you have, return that.
So let's make an object:
>>> c1 = Copyable(1, [2])
And copy
makes a shallow copy:
>>> c2 = copy(c1)
>>> c1 is c2
False
>>> c2.b.append(3)
>>> c1.b
[2, 3]
And deepcopy
now makes a deep copy:
>>> c3 = deepcopy(c1)
>>> c3.b.append(4)
>>> c1.b
[2, 3]
Shallow copy with copy.copy()
#!/usr/bin/env python3
import copy
class C():
def __init__(self):
self.x = [1]
self.y = [2]
# It copies.
c = C()
d = copy.copy(c)
d.x = [3]
assert c.x == [1]
assert d.x == [3]
# It's shallow.
c = C()
d = copy.copy(c)
d.x[0] = 3
assert c.x == [3]
assert d.x == [3]
Deep copy with copy.deepcopy()
#!/usr/bin/env python3
import copy
class C():
def __init__(self):
self.x = [1]
self.y = [2]
c = C()
d = copy.deepcopy(c)
d.x[0] = 3
assert c.x == [1]
assert d.x == [3]
Documentation: https://docs.python.org/3/library/copy.html
Tested on Python 3.6.5.
I believe the following should work with many well-behaved classed in Python:
def copy(obj):
return type(obj)(obj)
(Of course, I am not talking here about "deep copies," which is a different story, and which may be not a very clear concept -- how deep is deep enough?)
According to my tests with Python 3, for immutable objects, like tuples or strings, it returns the same object (because there is no need to make a shallow copy of an immutable object), but for lists or dictionaries it creates an independent shallow copy.
Of course this method only works for classes whose constructors behave accordingly. Possible use cases: making a shallow copy of a standard Python container class.
참고URL : https://stackoverflow.com/questions/4794244/how-can-i-create-a-copy-of-an-object-in-python
'Programing' 카테고리의 다른 글
git 저장소에 여러 프로젝트를 배치하는 가장 좋은 방법은 무엇입니까? (0) | 2020.06.06 |
---|---|
역 반복자를 사용하여 지우기를 호출하는 방법 (0) | 2020.06.06 |
캐시 없음과 재확인의 차이점 (0) | 2020.06.06 |
virtualenv에 해당하는 루비? (0) | 2020.06.06 |
정적 확장 방법 (0) | 2020.06.06 |