For mathematicians, operators are important to their thinking. Take a simple operation, like adding two numbers, and try to learn some of its behavior.
add (x, y) == add (y, x) (1)
Equation (1) expresses the law that addition is commutative. This is usually written using the operator, making it more concise:
x + y == y + x (1a)
This seems like a slight gain. Now consider the associative law:
add (x, add (y, z)) == add (add (x, y), z) (2)
Equation (2) can be rewritten using the operators:
x + (y + z) == (x + y ) + z (2a)
This is much less confusing than (2) and leads to the observation that the parentheses are redundant, so we can now write
x + y + z (3)
Many other laws are also written more easily using operators. Here’s another example about the addition identification element:
add (x, 0) == add (0, x) == x (4)
compare with this notation:
x + 0 == 0 + x == x (4a)
The general idea here is that once you learn this simple notation, equations written using them will be easier to “manipulate” than equations written using functional notation.
Perhaps everyone will agree with the statement that formulas written with operators are better understood. This process is subconscious, but thanks to it we understand what we actually see. For example, “chair”, not “pieces of wood connected in a certain way.” Writing in the form of functions attracts other parts of our brain, less subconscious (this is associated with reading and reading comprehension).
The power of visual perception becomes apparent when we use multiple operators. Let’s consider the distributive law:
mul (n, add (x, y)) == add (mul (n, x), mul (n, y)) (5).
It was painful to write this. In addition, most readers will not even immediately understand that this is the same distributive law.
Let’s compare it with this notation form:
n (x + y) == nx + ny (5b)
but unfortunately this is currently beyond the capabilities of the Python parser.
Another very powerful aspect of operator notation is that it can be conveniently applied to different types of objects. For example, laws (1) – (5) also work when x
, y
and z
are vectors of the same size and n is a scalar (replacing the vector of zeros to the literal “0
“, and also if they are matrices (again, n must be a scalar).
And you can do this with objects in different domains. For example, the above laws (1) – (5) apply to functions (n is again a scalar).
When choosing operators, mathematicians use their visual perception as an assistant: in this way they discover new laws faster.
Now programming is different from mathematics. But we all know that readability matters, and this is where operator overloading comes into play in Python. As soon as you have mastered the simple properties of operators, you understand that +
for concatenating strings or a list looks more readable, and above we have already partially explained why this is so.
Of course, you can overdo it – then you get Perl. But we often forget that it is much easier to understand the following entry:
d = d1 + d2
compared to this:
d = d1.copy ( ) d.update (d2)
and it’s not just about fewer lines of code: the first form allows us to use our visual processing to help us see meaning faster – and without distracting other parts of our brain (which may already be busy keeping track of the meaning of d1 and d2, for example).
Of course, everything has its price. It is necessary to study the operators and their properties when applied to different types of objects. (This is also true in mathematics – for numbers it is justified x * y == y * x
, but this property does not apply to functions or matrices, on the other hand, x+y == y+x
(association law) holds for all types.)
Many people are concerned about the issue of performance. I believe that readability comes first, and then performance comes next. If we return to the example with d = d1 + d2
, we will not see any loss in performance compared to the version without operators. In addition, there is a significant advantage in readability. It can be seen that in most situations the difference in performance is not so significant as to sacrifice readability. For those cases where performance comes to the fore, you can easily change the version with operators to something else (perhaps through profiling).