Deep copy operation on arbitrary Python objects. See the module's __doc__ string for more info.
(x, memo=None, _nil=[])
| 126 | del d, t |
| 127 | |
| 128 | def deepcopy(x, memo=None, _nil=[]): |
| 129 | """Deep copy operation on arbitrary Python objects. |
| 130 | |
| 131 | See the module's __doc__ string for more info. |
| 132 | """ |
| 133 | |
| 134 | if memo is None: |
| 135 | memo = {} |
| 136 | |
| 137 | d = id(x) |
| 138 | y = memo.get(d, _nil) |
| 139 | if y is not _nil: |
| 140 | return y |
| 141 | |
| 142 | cls = type(x) |
| 143 | |
| 144 | copier = _deepcopy_dispatch.get(cls) |
| 145 | if copier is not None: |
| 146 | y = copier(x, memo) |
| 147 | else: |
| 148 | if issubclass(cls, type): |
| 149 | y = _deepcopy_atomic(x, memo) |
| 150 | else: |
| 151 | copier = getattr(x, "__deepcopy__", None) |
| 152 | if copier is not None: |
| 153 | y = copier(memo) |
| 154 | else: |
| 155 | reductor = dispatch_table.get(cls) |
| 156 | if reductor: |
| 157 | rv = reductor(x) |
| 158 | else: |
| 159 | reductor = getattr(x, "__reduce_ex__", None) |
| 160 | if reductor is not None: |
| 161 | rv = reductor(4) |
| 162 | else: |
| 163 | reductor = getattr(x, "__reduce__", None) |
| 164 | if reductor: |
| 165 | rv = reductor() |
| 166 | else: |
| 167 | raise Error( |
| 168 | "un(deep)copyable object of type %s" % cls) |
| 169 | if isinstance(rv, str): |
| 170 | y = x |
| 171 | else: |
| 172 | y = _reconstruct(x, memo, *rv) |
| 173 | |
| 174 | # If is its own copy, don't memoize. |
| 175 | if y is not x: |
| 176 | memo[d] = y |
| 177 | _keep_alive(x, memo) # Make sure x lives at least as long as d |
| 178 | return y |
| 179 | |
| 180 | _deepcopy_dispatch = d = {} |
| 181 |