On May 1, 2020, at 10:27, gbs--- via Python-ideas <python-ideas@python.org> wrote:
In cases where it makes sense to do explicit type checking (with ABCs or whatever), I really detest the look of the isinstance() function.
if isinstance(thing, Fruit) and not isinstance(thing, Apple):
Yucky.
I think it’s intentional that it’s a little yucky. It makes you think “could I be using duck typing or overridden methods here instead of type switching?” Sure, sometimes the answer is, “No, I can’t,” which is why ABCs were added. But if you’re using them so often that you get annoyed by the ugliness, then maybe you’re using an antipattern—or, if not, there’s a good chance you’re doing something that’s perfectly valid but unusual for Python, so the language just isn’t going to cater to you. Maybe Python leans a little too far toward discouraging type checks, because there was so much resistance to the very idea of ABCs until people got used to them. But if so, I suspect you’ll need a solid example of realistic code that should look better, and can’t be reasonably redesigned, to convince people, not just showing that isinstance is about as ugly as it was designed to be.
What I really want to write is:
if thing is a Fruit and thing is not an Apple:
and after thinking about it on and off for a while I wonder if it might indeed be possible to teach the parser to handle that in a way that eliminates almost all possible ambiguity with the regular "is", including perhaps 100% of all existing standard library code and almost all user code?
Possible? Yes, at least with the new parser coming from PEP 617. But that doesn’t mean it’s a good idea. You certainly can’t make a and an into keywords, because lots of people have variables named a. You can’t even make them into “conditional keywords”, that only have a special meaning after “is” and “is not”—besides all the usual negatives of conditional keywords, it won’t work, because “b is a” is already perfectly reasonable code today. So you’d need to add some kind of backtracking: they’re conditional keywords only if they follow “is” or “is not” and are followed by a valid expression. Which is more complicated (and less efficient) to parse. Some third-party parser tools might even have to be completely rewritten, or at least to add special case hacks for this. And, more importantly, the more context it takes to parse things (or the more special cases you have to learn and memorize), the harder the language’s syntax is to internalize. The fact that Python is (almost) an LL(1) language makes it pretty easy to get most of syntax for the subset that you use firmly into your head. Every special case makes that less true, which means more cases where you get confused by a SyntaxError in your code or about what someone else’s code means, and means it’s harder to manually work through the parse when you do get stumped like that and you resort to shotgun-debugging antics instead. For a practical example, look at some languages that are actually designed to be executable English rather than executable pseudocode, like AppleScript or Inform. The fact that “bring every window of the first app to the foreground” reads like a normal English sentence is pretty cool, but the fact that “bring the first window of every app to the foreground” gives you an error message about not knowing what the every is, and the only way to rewrite it is “tell every app to bring the first window of it to the foreground”, severely dampens the coolness factor.
Maybe this has been considered at some point in the past? The "is [not] a|an" proposal would at least be a strong contender for "hardest thing to search for on the internet" lol.
That will also make it hard to search for when you see some code you don’t understand and need to search for help, won’t it? A search for “isinstance” (even without including Python) brings me the docs page, some tutorials and blogs, and some StackOverflow questions; what’s a search for “is a” or even “Python is a” going to get me? Maybe you could get more mileage out of going halfway there, with an operator named isa. Other languages use that spelling for related things (in Perl it’s exactly the operator you want; in ObjC it’s a property on the instance but it’s still about types), and people often use “isa” or “is-a” as a technical term in comp sci. if thing isa Fruit and thing not isa Apple: That’s still pretty readable, and easy to parse. But it still breaks backward compatibility, because people do have code that uses “isa” as a normal identifier. (For one thing, it’s how you access the isa attribute of an ObjC object in PyObjC.)