In C/C++/Java, the increment or decrement of integer variables is standard. They can be divided into prefix operations (++ I and — I) and suffix operations (I ++ and I –), but each has a slightly different purpose.

Users of these languages, when exposed to Python, might wonder why it doesn’t provide ++ or — operations. In my recent post “Python’s 100,000 Whys?” Many students expressed their interest in this topic in the questionnaire.

The ++ I prefix is possible in Python, but it does not have the “++” increment operator. It is simply a superposition of two “+” (positive symbols). The suffix “++” is not supported at all (SyntaxError: invalid syntax).

In this installment of “why Python”, we’ll answer the question from two main perspectives: why doesn’t Python support i++ increment syntax? (PS: Autoincrement refers to “autoincrement and subtraction”, the same below)

First of all, Python can of course increment itself by writing I += 1 or I = I + 1, which is common in other languages as well.

Although Python uses different magic methods (__add__() and __iadd__()) at the bottom to do the calculation, the effect on the surface is exactly the same.

So, the question becomes: why did the two above override i++ as Python’s ultimate choice?

1. Python integers are immutable types

When we define I = 1000, different languages do different things:

  • C and other languagesint i = 1000) allocates a block of memory, “binds” it with a fixed name I, and writes a variable value of 1000. Here, the address and type of I are fixed, and the value is variable (within a range of representations)
  • Python (writingi = 1000), but it “binds” to the number 1000, which is immutable in terms of address and type. In the case of I, it is just a name tag attached to 1000, which has no fixed address or type

So when we “increment” I (I = I + 1), they are treated differently:

  • A language like C finds the value stored at the address of I and increments it by one, replacing the old value
  • Python does this by adding one to the number I points to, binding the result to a newly allocated chunk of memory, and “attaching” the name tag I to the new number. Old and new numbers can coexist, not be substituted

An unfortunate analogy: the “I” in C is like a host on which the number 1000 lives; In Python, 1000 is like a host on which the name I lives. The I in C and the 1000 in Python live on the underlying memory space…

The variable I in C is a first-class citizen, and the number 1000 is a variable attribute of it; The number 1000 in Python is a first-class citizen, and the name I is a mutable attribute of it.

With the above matting, let’s take a look at i++, it is not difficult to find:

  • A language like C, I ++ can represent an increase in the numeric properties of I, it does not open up new memory space, nor does it create new first-class citizens
  • For languages like Python, I ++ would be meaningless if it were an operation on its name attribute. The situation becomes complicated if you understand the operation of a pair of digital ontologies: It will generate a new first-class citizen 1001, so it needs to allocate a memory address to it. At this time, if the address of 1000 is occupied, the old object will be recycled, and the original reference relationship to 1000 will be affected, so we can only create a new memory space for 1001

If Python supports i++, the operation is more complicated than C’s i++, and it no longer means “increment a number by one”, but “create a new number”, in which case the increment operator does not live up to its name.

Python could theoretically implement the I ++ operation, but it would have to redefine the increment operator, and it would be confusing for people with experience with other languages, so let’s just write I += 1 or I = I + 1.

2. Python has iterables

I++ is designed to facilitate the use of a three-paragraph for structure:

for(int i = 0; i < 100; i++){
    / / XXX
}
Copy the code

This kind of program is concerned with the increment process of the numbers themselves, and the addition of numbers is associated with the execution of the program body.

Python does not have this for structure. It provides a more elegant way of writing:

for i in range(100) :# XXX execution

my_list = ["Hello"."I'm a Python cat."."Welcome to your attention"]
for info in my_list:
    print(info)
Copy the code

There is a different way of thinking here, which is concerned with iterating over a range of values and does not care about or need to add numbers artificially.

Iterables/iterators/generators in Python provide a very good use of iterating/traversing and are a complete substitute for i++.

For example, to iterate over a value in a list is done in the above example. Python can also iterate over both subscripts and specific values with enumerate() :

my_list = ["Hello"."I'm a Python cat."."Welcome to your attention"]
for i, info in enumerate(my_list):
    print(i, info)

# Print result:
0hello1I'm a Python cat2Welcome to attentionCopy the code

For dictionary traversal, Python provides keys(), values(), items(), and other traversal methods, which are very useful:

my_dict = {'a': '1'.'b': '2'.'c': '3'}
for key in my_dict.keys():
    print(key)

for key, value in my_dict.items():
    print(key, value)
Copy the code

With such a weapon, where would i++ be used?

Moreover, I += 1 or I = I + 1 is rarely used in Python, and with the ubiquity of iterables, it’s easy for developers to operate on a range of values, and there’s little need to add up values.

So, to return to our initial question, these two “increment” methods don’t actually win much over i++, simply because they are generic and don’t require the introduction of new operators, so Python continues a foundational support. The real winners are all sorts of iterables!

A quick summary: Python does not support the increment operator, partly because its integers are first-class citizens of immutable type, and the increment operator (++) would be ambiguous to support; On the other hand, it has a more appropriate implementation, iterable objects, with good support for traversal operations.

If you think this analysis is good, you will enjoy these articles:

1. Why does Python use indentation to divide code blocks?

2. Is Python’s indentation anti-human?

3. Why does Python use semicolons as statement terminators?

4. Why does Python have a main function? Why don’t I recommend main?

5. Why does Python recommend serpentine nomenclature?

Last: This article is part of the “Why Python” series, which focuses on the syntax, design, and development of Python. The series tries to show the charm of Python by asking “why” questions. Some topics will be launched video version, please watch in B station, watch the address: video address

Python cat is a series of articles, including why Python series, Cat philosophy series, Python Advanced series, good books recommended series, technical writing, quality English recommendation and translation, and so on.