Message361371
Joachim:
> It's possible to use a tuple subclass, though, and while it doesn't break the function because it reads , the tuple is not explored through the __iter__ interface: (...)
I don't think that the example from the first message is an issue in isinstance(). Defining __iter__() does not override __getitem__() nor __len__():
---
class T(tuple):
def __iter__(self):
print("__iter__")
yield self
inst = T(("a", "b"))
print(len(inst))
print(inst[0])
print(inst[1])
---
Output:
---
2
a
b
---
But isinstance() doesn't call overriden __getitem__() and __len__() methods, only tuple.__getitem__() and tuple.__len__() original methods.
Joachim:
> Solutions could be handling any iterable but explicitely checking for recursion or, as suggested by Victor Stinner, forbidding subclasses of tuple.
isinstance() should use PyTuple_CheckExact(): only accept the exact tuple type, and reject any other type.
We can start by deprecating tuple subclasses in Python 3.9.
Paul:
> Should we switch to using __iter__ when it's defined because there are other cases where the custom behavior of the subclass is defined by its __iter__?
I just restored an old comment from Guido van Rossum which was lost in a previous refactoring, commit 850a4bd839ca11b59439e21dda2a3ebe917a9a16:
if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to
recursion and stack overflow. */
...
}
--
By the way, nested tuples are accepted:
>>> isinstance(1, ((((int,),),),))
True
I am -0 on nested tuples. The implementation is not so crazy (simple recursive code), so it is maybe ok to keep it. |
|
Date |
User |
Action |
Args |
2020-02-04 21:31:43 | vstinner | set | recipients:
+ vstinner, serhiy.storchaka, p-ganssle, ewjoachim |
2020-02-04 21:31:43 | vstinner | set | messageid: <1580851903.5.0.923043006119.issue39550@roundup.psfhosted.org> |
2020-02-04 21:31:43 | vstinner | link | issue39550 messages |
2020-02-04 21:31:43 | vstinner | create | |
|