The “problem” with runtime checkable protocols afaiu is that isinstance checks are fairly slow as they need to inspect the type and see that all interfaces comply. This can easily be avoided if you write code differently. With ABCs on the other hand, you just check that the type is in a list, which is much faster.
If I were in your situation, I would either write a custom Protocol that implements the Queue interface, and keep it non runtime-checkable until required just to see if you need it or not, or write an ABC implementing the interface and add the Queues to it’s implementations using the register class method. Both are equally valid Python and will achieve the same result, tho I prefer the former. Try both and see which you like best!
As a broader discussion, don’t you think that unifying these cousin classes under a common base type would be a good thing for the language? If it were to be added, would it belong in _collections_abc.py ? (in which case, for the sake of consistency with existing containers, one would likely chose an ABC?)
I don’t think there’s any benefit in uniting them beyond it being aesthetically pleasing. Most of the other collection protocols and ABCs were probably added because those interfaces are commonly implemented by users, and I don’t see the thread-safe Queue being used as an interface that custom classes implement being a common occurence. So unless people start implementing that interface often I don’t think there’s a need for a Protocol or ABC to exist, like Paul suggests, especially since those are trivial to write yourself.
Yes, it’s currently duck typed, but the user is asking for a common base class. Yes, I agree that it could be a protocol, but there are only advantages to making it an ABC (assuming we remove the metaclass).
Yes, but the only reason you’ve given so far is that you like them more because they’re newer. Also, you’re assuming that no one will ever want to do isinstance(x, Queue), which I don’t think is a reasonable limitation.
I think we’re getting at different things here. By ABC, I mean it in the computer science sense of the word: just an ordinary base class with abstract methods (no metaclass). In that sense, the protocol is “more machinery”.
I agree with you that the registration is superfluous machinery. But inheriting from ABCs is the standard way of declaring that your class implements an interface. And as mentioned above, this has superior behavior when doing instance checks. Really, protocol has no advantages for this case and many disadvantages.
What’s the impact of the ABC? One extra entry in the MRO? I don’t think this is a reasonable thing to worry about.
That’s a fair point. However, in general, someone may want to do isinstance on the base class, and it should work well in my opinion—even if the OP doesn’t need it for his use case.
Sorry, I guess I misread it: I thought you said that you liked them because they were newer. I missed the “not”.
However, you did argue that you prefer them because they’re worse at “isinstance”, and you argued that isinstance checks are proof of bad design. I don’t think that’s true or a reasonable limitation.
No it’s not - in Python, the standard way of declaring that your class implements an interface, going all the way back to Python 1.4 (and probably earlier, but that’s the first version I remember using) is to say it does. Duck typing is fundamental to Python’s design. Yes, there are now other approaches, including ABCs, but no one way should be seen as the “one true approach”.
Please can you take a breath, and stop making such absolute statements. There are different approaches available, and they have different trade-offs. Insisting that your preferred way is the “standard” one isn’t helping the discussion, and is bordering on a CoC violation (“Being respectful of differing viewpoints and experiences”).
I suggest that everyone take a break from posting in this thread - it’s going in an unproductive direction. I shall certainly be doing so.
I never said I prefer Protocols because they are worse at isinstance checks, in fact, in _my first response to you in this thread:
Don’t make up stuff I didn’t say just so you can keep on arguing.
In general, it’s basically impossible to discuss with you because you won’t leave it at me disagreeing with you. I’ve tried to disarm this discussion multiple to leave it at agree to disagree, and now you’ve even been making up reasons to continue arguing. I won’t reply to you anymore in this thread.
Sorry if that was too strong wording, but I think it would help to clarify what I meant.
By declare, I meant declare to all participants: declare to the type checker, declare to anyone doing introspection at runtime, and declare to the reader.
Yes, you can tell the reader with a comment that your class implements some interface.
However, if you want the type checker to know that it does, you can:
inherit, or
make the interface a protocol (and possibly assert on the type so that you’ll get a type error on deviation)
Finally, if you want runtime introspection to work, then
inheritance gives you that for free
you can make your protocol runtime-checkable.
I just meant that declaring in all these three ways is most commonly done using ordinary inheritance where possible. I agree that comments are fine if you just want to talk to readers, and I agree that protocols are a better solution in the situation where you can’t easily change all inheritors, or where you don’t care about runtime-checking.
Anyway, sorry if I my last statement was a bit passionate.
There would be other benefits to a protocol + documentation for the described use case, as the code in question is already duck typed in behavior. Changing it to an ABC would be more restrictive than the runtime actually is in the OP’s case.
The problem with ABCs is that they push inheritance patterns rather than just work with normal duck-typed python code, especially when the protocol isn’t providing a base behavior, only expressing statically, as well as to tools that pick up on that such as IDEs, an expectation of interface.
Perhaps I’m just quant, but I keep going back to PEP 484:
It should also be emphasized that Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention.
In my opinion, duck typed Python is inherently elegant. While I often type hint code that I’m writing, I don’t see a need to type longstanding classes like the Queues.