Hướng dẫn how do you duplicate an object in python? - làm thế nào để bạn sao chép một đối tượng trong python?

Làm cách nào để tạo một bản sao của một đối tượng trong Python?

Vì vậy, nếu tôi thay đổi giá trị của các trường của đối tượng mới, đối tượng cũ không nên bị ảnh hưởng bởi điều đó.

Bạn có nghĩa là một đối tượng có thể thay đổi sau đó.

Trong Python 3, danh sách nhận được phương thức

>>> 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'}}]
3 (trong 2, bạn sẽ sử dụng một lát để tạo một bản sao):

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

Bản sao nông

Bản sao nông chỉ là bản sao của container ngoài cùng.

>>> 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'}}]
4 là một bản sao nông:

>>> 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'}}]

Bạn không nhận được một bản sao của các đối tượng nội thất. Chúng là cùng một đối tượng - vì vậy khi chúng bị đột biến, sự thay đổi hiển thị trong cả hai container.

Bản sao sâu

Bản sao sâu là bản sao đệ quy của mỗi đối tượng nội thất.

>>> 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'}}]

Thay đổi không được phản ánh trong bản gốc, chỉ trong bản sao.

Đối tượng bất biến

Các đối tượng bất biến thường không cần phải sao chép. Trên thực tế, nếu bạn cố gắng, Python sẽ chỉ cung cấp cho bạn đối tượng ban đầu:

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

Tuples thậm chí không có một phương thức sao chép, vì vậy hãy thử nó bằng một lát:

>>> tuple_copy_attempt = a_tuple[:]

Nhưng chúng ta thấy đó là cùng một đối tượng:

>>> tuple_copy_attempt is a_tuple
True

Tương tự cho chuỗi:

>>> s = 'abc'
>>> s0 = s[:]
>>> s == s0
True
>>> s is s0
True

và đối với Frozensets, mặc dù chúng có phương pháp

>>> 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'}}]
3:

>>> a_frozenset = frozenset('abc')
>>> frozenset_copy_attempt = a_frozenset.copy()
>>> frozenset_copy_attempt is a_frozenset
True

Khi nào nên sao chép các đối tượng bất biến

Các đối tượng bất biến nên được sao chép nếu bạn cần một đối tượng nội thất có thể thay đổi được sao chép.

>>> 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'],)

Như chúng ta có thể thấy, khi đối tượng bên trong của bản sao bị đột biến, bản gốc không thay đổi.

Đối tượng tùy chỉnh

Các đối tượng tùy chỉnh thường lưu trữ dữ liệu trong thuộc tính

>>> 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'}}]
6 hoặc trong
>>> 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'}}]
7 (cấu trúc bộ nhớ giống như tple.)

Để tạo một đối tượng có thể sao chép, hãy xác định

>>> 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'}}]
8 (cho các bản sao nông) và/hoặc
>>> 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'}}]
9 (cho các bản sao sâu).

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

Lưu ý rằng

>>> 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'}}]
0 giữ một từ điển ghi nhớ củ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'}}]
1 (hoặc số nhận dạng) cho các bản sao. Để tận hưởng hành vi tốt với các cấu trúc dữ liệu đệ quy, hãy chắc chắn rằng bạn đã không tạo một bản sao và nếu bạn có, hãy trả lại điều đó.

Vì vậy, hãy tạo một đối tượng:

>>> 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'}}]
0

>>> 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'}}]
3 tạo ra một bản sao nông:

>>> 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'}}]
1

>>> 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'}}]
0 hiện tạo ra một bản sao sâu:

>>> 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'}}]
2

Mã nguồn: lib/copy.py Lib/copy.py


Các câu lệnh gán trong Python không sao chép các đối tượng, chúng tạo ra các ràng buộc giữa mục tiêu và đối tượng. Đối với các bộ sưu tập có thể thay đổi hoặc chứa các mục có thể thay đổi, đôi khi một bản sao là cần thiết để người ta có thể thay đổi một bản sao mà không thay đổi cái kia. Mô -đun này cung cấp các hoạt động sao chép nông và sâu chung (giải thích bên dưới).

Tóm tắt giao diện:

sao chép.Copy (x) ¶copy(x)

Trả lại một bản sao nông của x.

sao chép.deepcopy (x [, memo]) ¶deepcopy(x[, memo])

Trả lại một bản sao sâu của x.

ExceptionCopy.error¶ copy.Error

Được nâng lên cho các lỗi cụ thể của mô -đun.

Sự khác biệt giữa sao chép nông và sâu chỉ có liên quan đến các đối tượng hỗn hợp (các đối tượng có chứa các đối tượng khác, như danh sách hoặc trường hợp lớp):

  • Một bản sao nông xây dựng một đối tượng hợp chất mới và sau đó (trong phạm vi có thể) chèn các tham chiếu vào nó vào các đối tượng được tìm thấy trong bản gốc.

  • Một bản sao sâu xây dựng một đối tượng hợp chất mới và sau đó, đệ quy, chèn các bản sao vào nó của các đối tượng được tìm thấy trong bản gốc.

Hai vấn đề thường tồn tại với các hoạt động sao chép sâu mà don lồng tồn tại với các hoạt động sao chép nông:

  • Các đối tượng đệ quy (các đối tượng hợp chất, trực tiếp hoặc gián tiếp, chứa một tham chiếu đến chính chúng) có thể gây ra một vòng lặp đệ quy.

  • Bởi vì bản sao sâu sao chép mọi thứ mà nó có thể sao chép quá nhiều, chẳng hạn như dữ liệu dự định được chia sẻ giữa các bản sao.

Hàm

>>> 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'}}]
4 tránh những vấn đề này bằng cách:

  • Giữ một từ điển

    >>> 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'}}]
    
    5 của các đối tượng đã được sao chép trong quá trình sao chép hiện tại; và

  • Cho phép các lớp do người dùng xác định ghi đè hoạt động sao chép hoặc tập hợp các thành phần được sao chép.

Mô -đun này không sao chép các loại như mô -đun, phương thức, dấu vết ngăn xếp, khung ngăn xếp, tệp, ổ cắm, cửa sổ hoặc bất kỳ loại tương tự nào. Nó không sao chép các chức năng và các lớp (nông và sâu), bằng cách trả về đối tượng ban đầu không thay đổi; Điều này tương thích với cách chúng được xử lý bằng mô -đun

>>> 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'}}]
6.

Các bản sao nông của từ điển có thể được thực hiện bằng cách sử dụng

>>> 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'}}]
7 và các danh sách bằng cách gán một lát của toàn bộ danh sách, ví dụ,
>>> 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'}}]
8.

Các lớp có thể sử dụng các giao diện tương tự để kiểm soát sao chép mà họ sử dụng để kiểm soát Pickling. Xem mô tả của mô -đun

>>> 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'}}]
6 để biết thông tin về các phương pháp này. Trên thực tế, mô -đun
>>> 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'
0 sử dụng các hàm Pickle đã đăng ký từ mô -đun
>>> 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'
1.

Để một lớp xác định triển khai bản sao của riêng mình, nó có thể xác định các phương thức đặc biệt

>>> 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'
2 và
>>> 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'
3. Cái trước được gọi để thực hiện hoạt động sao chép nông; Không có lập luận bổ sung được thông qua. Cái sau được gọi để thực hiện hoạt động sao chép sâu; Nó được thông qua một đối số, từ điển
>>> 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'}}]
5. Nếu việc triển khai
>>> 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'
3 cần tạo một bản sao sâu của một thành phần, nó sẽ gọi hàm
>>> 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'}}]
4 với thành phần là đối số đầu tiên và từ điển ghi nhớ là đối số thứ hai. Từ điển ghi nhớ nên được coi là một đối tượng mờ đục.

Xem thêm

Mô -đun
>>> 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'}}]
6

Thảo luận về các phương pháp đặc biệt được sử dụng để hỗ trợ truy xuất và phục hồi trạng thái đối tượng.

Làm thế nào một đối tượng được sao chép trong Python?

Trong trường hợp sao chép nông, một tham chiếu của một đối tượng được sao chép vào một đối tượng khác.Nó có nghĩa là bất kỳ thay đổi nào được thực hiện đối với một bản sao của một đối tượng đều phản ánh trong đối tượng gốc.Trong Python, điều này được triển khai bằng cách sử dụng hàm Copy Copy ().using the “copy()” function.

__ mới __ trong Python là gì?

__New__ là phương thức lớp tĩnh, trong khi __init__ là phương thức thể hiện.__New__ phải tạo phiên bản đầu tiên, vì vậy __init__ có thể khởi tạo nó.Lưu ý rằng __init__ lấy tự làm tham số.Cho đến khi bạn tạo ví dụ, không có bản thân.Bây giờ, tôi tập hợp, rằng bạn đang cố gắng thực hiện mẫu Singleton trong Python.static class method, while __init__ is instance method. __new__ has to create the instance first, so __init__ can initialize it. Note that __init__ takes self as parameter. Until you create instance there is no self . Now, I gather, that you're trying to implement singleton pattern in Python.