copy.copy()/copy.deepcopy() of deque and array subclasses drop instance attributes (array also changes type)
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
Bug report
copy.copy() of a collections.deque subclass, and both copy.copy() and copy.deepcopy() of an array.array subclass, silently drop the instance __dict__. For array the result is also a plain array rather than the subclass. pickle preserves both, and list/dict/set subclasses behave correctly, so this is an inconsistency.
Reproducer
import copy, pickle
from collections import deque
from array import array
class D(deque): pass
d = D([1, 2, 3]); d.label = "kept"
print("deque copy :", getattr(copy.copy(d), "label", "LOST"))
print("deque deepcopy:", getattr(copy.deepcopy(d), "label", "LOST"))
print("deque pickle :", getattr(pickle.loads(pickle.dumps(d)), "label", "LOST"))
class A(array): pass
a = A("i", [1, 2, 3]); a.tag = "kept"
print("array copy :", type(copy.copy(a)).__name__, getattr(copy.copy(a), "tag", "LOST"))
print("array deepcopy:", type(copy.deepcopy(a)).__name__, getattr(copy.deepcopy(a), "tag", "LOST"))
print("array pickle :", type(pickle.loads(pickle.dumps(a))).__name__, getattr(pickle.loads(pickle.dumps(a)), "tag", "LOST"))
Output:
deque copy : LOST
deque deepcopy: kept
deque pickle : kept
array copy : array LOST
array deepcopy: array LOST
array pickle : A kept
A list subclass (and dict/set) preserves the type and attribute in all three cases, which is the expected behavior:
class L(list): pass
l = L([1, 2, 3]); l.label = "kept"
copy.copy(l).label # 'kept'
type(copy.copy(l)) # <class '__main__.L'>
Expected
copy.copy()/copy.deepcopy() should return an object of the same (sub)class with the instance attributes preserved, matching pickle and the behavior of list/dict/set subclasses.
Cause
deque.__copy__ (deque_copy in Modules/_collectionsmodule.c) and array.__copy__/__deepcopy__ (Modules/arraymodule.c) build the new object without copying the instance __dict__; the array versions also don't construct the actual subclass. Each type's __reduce_ex__ already captures the subclass and the __dict__ (that's why pickle and deepcopy-of-deque work), so the custom __copy__/__deepcopy__ shortcuts are what diverge.
Versions
Reproduces on main (3.16.0a0) and 3.12.7.
Linked PRs
- gh-152043
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Đọc Modules/_collectionsmodule.c tại deque_copy và Modules/arraymodule.c tại các phương thức sao chép của array, sau đó dùng reproducer để so sánh kiểu lớp con và các thuộc tính của instance với pickle và các lớp con của list. Hoàn tất có nghĩa là copy.copy() và copy.deepcopy() giữ nguyên lớp con và các thuộc tính của instance đối với deque và array, kèm theo coverage hồi quy.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, python
- Lĩnh vực
- backend
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 30/100