Saturday 25 May 2019 — This is over five years old. Be careful.
If you’ve used any programming language for a long enough time, you’ve found things about it that you wish were different. It’s true for me with Python. I have ideas of a number of things I would change about Python if I could. I’ll bore you with just one of them: the syntax of class definitions.
But let’s start with the syntax for defining functions. It has this really nice property: function definitions look like their corresponding function calls. A function is defined like this:
def func_name(arg1, arg2):
When you call the function, you use similar syntax: the name of the function, and a comma-separated list of arguments in parentheses:
x = func_name(12, 34)
Just by lining up the punctuation in the call with the same bits of the definition, you can see that arg1 will be 12, and arg2 will be 34. Nice.
OK, so now let’s look at how a class with base classes is defined:
class MyClass(BaseClass, AnotherBase):
To create an instance of this class, you use the name of the class, and parens, but now the parallelism is gone. You don’t pass a BaseClass to construct a MyClass:
my_obj = MyClass(...)
Just looking at the class line, you can’t tell what has to go in the parens to make a MyClass object. So “def” and “class” have very similar syntax, and function calls and object creation have very similar syntax, but the mimicry in function calls that can guide you to the right incantation will throw you off completely when creating objects.
This is the sort of thing that experts glide right past without slowing down. They are used to arcane syntax, and similar things having different meanings in subtly different contexts. And a lot of that is inescapable in programming languages: there are only so many symbols, and many many more concepts. There’s bound to be overlaps.
But we could do better. Why use parentheses that look like a function call to indicate base classes? Here’s a better syntax:
class MyClass from BaseClass, AnotherBase:
Not only does this avoid the misleading punctuation parallelism, but it even borrows from the English we use to talk about classes: MyClass derives from BaseClass and AnotherBase. And “from” is already a keyword in Python.
BTW, even experts occasionally make the mistake of typing “def” where they meant “class”, and the similar syntax means the code is valid. The error isn’t discovered until the traceback, which can be baffling.
I’m not seriously proposing to change Python. Not because this wouldn’t be better (it would), but because a change like this is impractical at this late date. I guess it could be added as an alternative syntax, but it would be hard to argue that having two syntaxes for classes would be better for beginners.
But I think it is helpful to try to see our familiar landscape as confused beginners do. It can only help with explaining it to them, and maybe help us make better choices in the future.
Comments
class Thing(Parent, metaclass = Whatever):
In that parlance, class is simply a shortcut for "make type".
Yes, make should be a new keyword. But at least we could write the full name of first arguments to classmethods. :-D
The syntax for defining class attributes is perfectly fine. It's the instance attributes that are the problem, mostly because you don't have an instance until creation time.
Add a comment: