-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Inconsistency over Container
#397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Note that Python often lets you use
However, this does not work for strings, which probably should be containers as well:
So we could reasonably either restrict the argument of I'd like So there is no obvious right way to do this -- it seems that no matter what we choose, we can't type check some operations properly. Here are some compromises:
|
The fact that After all, part of the point of static type checking is not just that it can catch errors earlier, but that it can catch errors that are otherwise never caught unless you write specific unit tests for them. Consider this example: I'm writing some database-driven code, and I have a function that's supposed to take a new person's name and add a record to the Person table. If the caller passes me an As for your |
I agree that
In your example, passing an As for I'm still unsure about what's the best way to do this. |
I don't think that should be okay. Unless you want to define the contains method as contravariant (which a few languages would let you do, but I don't think you or anyone else has suggested that for MyPy), this is a type error. So a type checker should catch it. What do statically-typed languages do in this case? Let's look at C++:
Compile this, and you'll get a slew of errors, starting with:
OK, maybe I should have picked Java or Swift rather than C++, because C++ is mostly structurally-typed, so it's literally complaining about the lack of an implicit conversion from Animal to Cat (that is, that Animal can't compile-time-duck-type as a Cat) rather than the lack of an explicit subclass relationship. But it's the same problem, and every language will reject it. Of course you could argue that people have written code that takes advantage of the weak typing of contains and you don't want to break it. But you're not breaking it, you're just flagging it as a static type error, which it is. You can still run the code in Python and it will "work", just like my example of inserting an int into a sqlite str column will work, but that doesn't mean it's not something a type-checking linter should complain about. |
I think the biggest issue is whether Note that in Java, the corresponding methods work with arbitrary objects (I'm talking about
C# does not seem to have an immutable list/sequence type, and thus it only supports covariance with |
In
collections.abc
,Sequence
,Mapping
, andSet
all inherit fromContainer
.In
typing
,Sequence[T]
inherits fromContainer[T]
, whileMapping[T]
andAbstractSet[T]
do not, and instead define__contains__
, which meansContainer
picks them up as aProtocol
. Unless there's a reason these have to work differently, it seems like they should all inherit.Also,
Container
doesn't annotate its__contains__
method at all, andMapping
andAbstractSet
annotate it as taking anobject
. Shouldn't these all be requiringT
?The text was updated successfully, but these errors were encountered: