I do not know MicroPython at all, but I know Python moderately well and some aspects of the language very well.
Python is slower than traditional programming languages for several reasons.
The primary one is its use of dynamic typing. What that means is that variables are references (pointers) to objects. The type of the object(s) in question is determined at run time instead of by static processing of the source code.
So to "add" two variables,
a = b + c
something like the following must be done:
Code:
if b is not defined:
raise exception
if c is not defined:
raise exception
if b and c are not "+" compatible:
raise exception
"+" b and c
if a currently references an object:
delete the reference in systems implementing reference counting
store reference to the result of b + c in a
"+" can be addition of numbers, concatenation of strings, union of tuples, lists, etc
Note than in general, the result of b + c must be allocated from a pool of free memory.
The second factor is that integers vary in size; there is no hard size limit other than the amount of available free memory in the system. Since version 3, there are no fixed sizes of integers, meaning even simple arithmetic calculations bear the cost of dealing with variable precision and memory allocation.
The third reason is there is no character type. A character may be extracted from a string by slicing it into a new string containing a single character. And comparing two characters requires comparing two strings. Strings are immutable; replacing a character within a string requires creating a new string with the modification. All of this makes character processing such as parsing slower in Python than in more traditional languages.
The fourth factor is that functions in Python are overgeneralized. You can do something perverse like this:
Code:
def sum(a, b):
return a + b
def difference(a, b):
return a - b
print(sum(1, 2))
# yielding 3
sum = difference
print(sum(1, 2))
# yielding -1
Note that the two functions need not have the same number or types of arguments. Arguments may also be passed by name(keyword.)
For example, you can write:
Code:
one=1
print(one, 2, '3', sep=', ', end="...\n")
to get:
1, 2, 3...
What this means is that in order to call a function, a tuple is created with the positional arguments, a dictionary is created with the keyword arguments and the function name variable is confirmed as a reference to an actual function. Then and only then is control passed to the called function which has to varify the validity of data passed in via the tuple and the dictionary, raising an exception in case of a problem, before doing its work.
In light of all of this overhead, the fact that a Python program is converted into bytecode and interpreted is not really significant.
---
In the summer of 2015, I joined a couple of makerspaces.
Prior to that, I was learning the Atmel AVR using a development kit from XGameStation (Andre Lamoth's company.)
The makerspace experience showed me that both Python and the Arduino are hugely popular.
I had been avoiding the Arduino platform because I thought it was dumbed down. It used a simplified version of C/C++ as its programming language and did not offer assembly language as an option. Somehow, I had a mistaken impression it was a drag-and-drop environment not unlike the Lego Mindstorms robotics system. I found out that the Arduino was a very good platform for prototyping a project concept quickly. I became a fan, quit using the XGS set and even began teaching classes on applying the Arduino.
Likewise, Python was not only a scripting language, but it is good for rapidly trying an idea before implementing it with a more efficient traditional language. With the availability of many high quality libraries, it is sometimes even a suitable implementation language.
My thought was: Arduino is popular and Python is popular, so why can I not program an Arduino in Python? I set out to remedy that.
But the mainstream Arduino, the Uno, is based on the Atmel 328P microcontroller. With 16K words of flash program memory and 2K bytes of static RAM, it is half of the size of the 644P in my XGS development board. I had doubts that much of Python could be implemented in such a limited space.
Because the makerspace had a working Commodore C128 on display at the time, I decided to initially target the 6502 with a Python cross compiler. It is a slower processor, but with much more writeable memory.
The compiler converted a Python program into 6502 assembly language. The run-time library is responsible for implementing Pythonic behavior like variable precision integers and memory management.
The compiler is currently still very incomplete. Dynamic typing and memory management works. Most of the arithmetic operators for integers have been implemented. Functions like print are done. The ability to define a function is the next tough nut to crack.
---
I will not be implementing MicroPython. But I can offer assistance in the form of the code in the run-time library.