Open MestreLion opened 2 years ago
Some research indicates slicing (and by consequence .copy()
) should preserve type:
(1, 2, 3, 4)[1:3] == (2, 3)
, a strong argument for not returning plain lists.copy()
| creates a shallow copy of s (same as s[:]
)" - not only it officially ties slicing and copy, it also strongly suggests (both) should preserve typecollections.UserList.copy()
does preserve type, but slicing surprisingly doesn't ! Maybe a bug?numpy.ndarray
, even if supports slicing, does not support append()
or extend()
or any of the regular methods of the Mutable Sequence protocol, so it should not be considered.Given that, now I have a strong opinion that at least List|Compound.copy()
should preserve type, and so should slicing. You OK for a PR implementing this?
Yeah this can't be easily handled right now because lists and compounds inherit directly from the builtins instead of MutableSequence
and MutableMapping
, so you would need to manually override each method. Inheriting from the builtins has advantages but it seems that the pythonic way to do it is to go through the ABCs and wrap an underlying list
or dict
. However it could also be less efficient, and I'm not sure if ABCs play well with mypyc
if we go down that route, so this needs further investigation.
I was planning on overriding each method anyway, no problem with that. You're already overriding __getitem__
, I would just adjust it and add copy
and whatever additional methods are needed.
Yeah, ABCs used to be the norm, but there are legitimate cases for subclassing the builtins direcly. It used to be a chore and have a million caveats, but not anymore, specially in Python 3 (and even more with Protocols, etc). The builtins do inherit from the ABCs, so you can already use isinstance(Compound, MutableMapping)
. So I don't think it's worth converting tags to plain ABCs. You already had the trouble to deal with the builtins caveats (and this issue would improve that)
Hmmm, now I'm also wondering about other tags like numeric and strings. Should string slicing or methods like .lower()
return String
instances? Should mathematical operations also return wrappers? Currently things like Int(123) + Int(1)
return a builtin int
. I think it's worth considering if we end up implementing that for lists and compounds.
Hum, very interesting point!
Yeah, I believe they should preserve type too. Both str
and bytes
preserve type on .lower|upper()
(and I assume related methods too), and it would make API much smoother to use on numericals
I just noticed
List.copy()
returns a plainlist
, as it doesn't override the copy method, and was about to create a PR implementing it. Then I realized this is a deeper issue, so I need your opinion before moving on:list.copy() == list[:]
, so copy if was changed to preserve type, should slicing be changed too? I.e., shouldList.__getitem__
use the a similar logic as__setitem__
, and do something like this:if isinstance(index, slice): return self.__class__(super().__getitem__(index))
.It would be surprising if
copy()
preserve type but slicing didn't. In one hand, some might expect (and rely on) copy and slicing to return a plain list. OTOH, it's awkward to writeb = List[xxx](a.copy())
to preserve type and easy to dob = list(a.copy())
to guarantee a plain list.In a general way, should the mutables
Compound
andList
preserve type in slicing and subsets?I could do some research to see what
numpy.ndarray
and other similar list subclasses do, and also if there's any principle suggested incollections.abc.MutableSequence
.Meanwhile, what's your opinion on this? Interested in a PR to implement
copy()
and related methods in Compound and List?